mirror of
https://gitee.com/mafgwo/stackedit
synced 2024-11-15 19:22:27 +08:00
GitLab授权调整
This commit is contained in:
parent
80e0e3bc99
commit
12e4befa96
|
@ -77,6 +77,7 @@ StackEdit中文版
|
||||||
- 导出HTML、PDF支持带预览主题导出(2023-02-26)
|
- 导出HTML、PDF支持带预览主题导出(2023-02-26)
|
||||||
- 支持分享文档(2023-03-30)
|
- 支持分享文档(2023-03-30)
|
||||||
- 支持ChatGPT生成内容(2023-04-10)
|
- 支持ChatGPT生成内容(2023-04-10)
|
||||||
|
- GitLab授权接口调整(2023-08-26)
|
||||||
|
|
||||||
## 国外开源版本弊端:
|
## 国外开源版本弊端:
|
||||||
- 作者已经不维护了
|
- 作者已经不维护了
|
||||||
|
@ -113,6 +114,7 @@ services:
|
||||||
- GITEA_CLIENT_SECRET=【不需要支持则删掉】
|
- GITEA_CLIENT_SECRET=【不需要支持则删掉】
|
||||||
- GITEA_URL=【不需要支持则删掉】
|
- GITEA_URL=【不需要支持则删掉】
|
||||||
- GITLAB_CLIENT_ID=【不需要支持则删掉】
|
- GITLAB_CLIENT_ID=【不需要支持则删掉】
|
||||||
|
- GITLAB_CLIENT_SECRET=【不需要支持则删掉】
|
||||||
- GITLAB_URL=【不需要支持则删掉】
|
- GITLAB_URL=【不需要支持则删掉】
|
||||||
ports:
|
ports:
|
||||||
- 8080:8080/tcp
|
- 8080:8080/tcp
|
||||||
|
@ -149,6 +151,7 @@ docker run -itd --name stackedit \
|
||||||
-e GITEA_CLIENT_SECRET=【不需要支持则删掉】 \
|
-e GITEA_CLIENT_SECRET=【不需要支持则删掉】 \
|
||||||
-e GITEA_URL=【不需要支持则删掉】 \
|
-e GITEA_URL=【不需要支持则删掉】 \
|
||||||
-e GITLAB_CLIENT_ID=【不需要支持则删掉】 \
|
-e GITLAB_CLIENT_ID=【不需要支持则删掉】 \
|
||||||
|
-e GITLAB_CLIENT_SECRET=【不需要支持则删掉】 \
|
||||||
-e GITLAB_URL=【不需要支持则删掉】 \
|
-e GITLAB_URL=【不需要支持则删掉】 \
|
||||||
mafgwo/stackedit:【docker中央仓库找到最新版本】
|
mafgwo/stackedit:【docker中央仓库找到最新版本】
|
||||||
|
|
||||||
|
@ -163,7 +166,7 @@ docker run -itd --name stackedit \
|
||||||
|
|
||||||
- Gitea可选择性配置环境变量(未配置则在关联时前端指定,有配置则仅允许配置的应用信息):GITEA_CLIENT_ID、GITEA_CLIENT_SECRET、GITEA_URL,**[如何创建Gitea应用](./docs/部署之Gitea应用创建.md)**
|
- Gitea可选择性配置环境变量(未配置则在关联时前端指定,有配置则仅允许配置的应用信息):GITEA_CLIENT_ID、GITEA_CLIENT_SECRET、GITEA_URL,**[如何创建Gitea应用](./docs/部署之Gitea应用创建.md)**
|
||||||
|
|
||||||
- Gitlab可选择性配置环境变量(未配置则在关联时前端指定,有配置则仅允许配置的应用信息):GITLAB_CLIENT_ID、GITLAB_URL **如何创建Gitlab应用(待补充文档)**
|
- Gitlab可选择性配置环境变量(未配置则在关联时前端指定,有配置则仅允许配置的应用信息):GITLAB_CLIENT_ID、GITLAB_CLIENT_SECRET、GITLAB_URL **如何创建Gitlab应用(待补充文档)**
|
||||||
|
|
||||||
(特别说明:自建的Gitea、Gitlab要能接入stackedit必须支持跨域)
|
(特别说明:自建的Gitea、Gitlab要能接入stackedit必须支持跨域)
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ module.exports = merge(prodEnv, {
|
||||||
// GITEA_CLIENT_ID: '"fe30f8f9-b1e8-4531-8f72-c1a5d3912805"',
|
// GITEA_CLIENT_ID: '"fe30f8f9-b1e8-4531-8f72-c1a5d3912805"',
|
||||||
// GITEA_CLIENT_SECRET: '"lus7oMnb3H6M1hsChndphArE20Txr7erwJLf7SDBQWTw"',
|
// GITEA_CLIENT_SECRET: '"lus7oMnb3H6M1hsChndphArE20Txr7erwJLf7SDBQWTw"',
|
||||||
// GITEA_URL: '"https://gitea.test.com"',
|
// GITEA_URL: '"https://gitea.test.com"',
|
||||||
// GITLAB_CLIENT_ID: '"33e01128c27fe75df3e5b35218d710c7df280e6ee9c90b6ca27ac9d9fdfb92f7"',
|
GITLAB_CLIENT_ID: '"074cd5103c62dea0f479dac861039656ac80935e304c8113a02cc64c629496ae"',
|
||||||
// GITLAB_URL: '"http://gitlab.qicoder.com"',
|
GITLAB_CLIENT_SECRET: '"6f406f24216b686d55d28313dec1913c2a8e599afdb08380d5e8ce838e16e41e"',
|
||||||
|
GITLAB_URL: '"http://gitlab.qicoder.com"',
|
||||||
})
|
})
|
|
@ -15,6 +15,7 @@ const giteaClientId = process.env.GITEA_CLIENT_ID;
|
||||||
const giteaClientSecret = process.env.GITEA_CLIENT_SECRET;
|
const giteaClientSecret = process.env.GITEA_CLIENT_SECRET;
|
||||||
const giteaUrl = process.env.GITEA_URL;
|
const giteaUrl = process.env.GITEA_URL;
|
||||||
const gitlabClientId = process.env.GITLAB_CLIENT_ID;
|
const gitlabClientId = process.env.GITLAB_CLIENT_ID;
|
||||||
|
const gitlabClientSecret = process.env.GITLAB_CLIENT_SECRET;
|
||||||
const gitlabUrl = process.env.GITLAB_URL;
|
const gitlabUrl = process.env.GITLAB_URL;
|
||||||
|
|
||||||
exports.values = {
|
exports.values = {
|
||||||
|
@ -33,6 +34,9 @@ exports.values = {
|
||||||
giteaClientId,
|
giteaClientId,
|
||||||
giteaClientSecret,
|
giteaClientSecret,
|
||||||
giteaUrl,
|
giteaUrl,
|
||||||
|
gitlabClientId,
|
||||||
|
gitlabClientSecret,
|
||||||
|
gitlabUrl,
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.publicValues = {
|
exports.publicValues = {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
const qs = require('qs');
|
|
||||||
const request = require('request');
|
const request = require('request');
|
||||||
const conf = require('./conf');
|
const conf = require('./conf');
|
||||||
|
|
||||||
|
|
40
server/gitlab.js
Normal file
40
server/gitlab.js
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
const request = require('request');
|
||||||
|
const conf = require('./conf');
|
||||||
|
|
||||||
|
function gitlabToken(queryParam) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
request({
|
||||||
|
method: 'POST',
|
||||||
|
url: `${conf.values.gitlabUrl}/oauth/token`,
|
||||||
|
headers: {
|
||||||
|
'content-type': 'application/json',
|
||||||
|
},
|
||||||
|
json: true,
|
||||||
|
qs: {
|
||||||
|
...queryParam,
|
||||||
|
client_id: conf.values.gitlabClientId,
|
||||||
|
client_secret: conf.values.gitlabClientSecret,
|
||||||
|
},
|
||||||
|
}, (err, res, body) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
const token = body.access_token;
|
||||||
|
if (token) {
|
||||||
|
resolve(body);
|
||||||
|
} else {
|
||||||
|
reject(res.statusCode + ',body:' + JSON.stringify(body));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.gitlabToken = (req, res) => {
|
||||||
|
gitlabToken(req.query)
|
||||||
|
.then(
|
||||||
|
tokenBody => res.send(tokenBody),
|
||||||
|
err => res
|
||||||
|
.status(400)
|
||||||
|
.send(err ? err.message || err.toString() : 'bad_code'),
|
||||||
|
);
|
||||||
|
};
|
|
@ -5,6 +5,7 @@ const path = require('path');
|
||||||
const github = require('./github');
|
const github = require('./github');
|
||||||
const gitee = require('./gitee');
|
const gitee = require('./gitee');
|
||||||
const gitea = require('./gitea');
|
const gitea = require('./gitea');
|
||||||
|
const gitlab = require('./gitlab');
|
||||||
const pdf = require('./pdf');
|
const pdf = require('./pdf');
|
||||||
const pandoc = require('./pandoc');
|
const pandoc = require('./pandoc');
|
||||||
const conf = require('./conf');
|
const conf = require('./conf');
|
||||||
|
@ -28,6 +29,7 @@ module.exports = (app) => {
|
||||||
app.get('/oauth2/githubToken', github.githubToken);
|
app.get('/oauth2/githubToken', github.githubToken);
|
||||||
app.get('/oauth2/giteeToken', gitee.giteeToken);
|
app.get('/oauth2/giteeToken', gitee.giteeToken);
|
||||||
app.get('/oauth2/giteaToken', gitea.giteaToken);
|
app.get('/oauth2/giteaToken', gitea.giteaToken);
|
||||||
|
app.get('/oauth2/gitlabToken', gitlab.gitlabToken);
|
||||||
app.get('/conf', (req, res) => res.send(conf.publicValues));
|
app.get('/conf', (req, res) => res.send(conf.publicValues));
|
||||||
app.post('/pdfExport', pdf.generate);
|
app.post('/pdfExport', pdf.generate);
|
||||||
app.post('/pandocExport', pandoc.generate);
|
app.post('/pandocExport', pandoc.generate);
|
||||||
|
|
|
@ -263,8 +263,8 @@ export default {
|
||||||
},
|
},
|
||||||
async addGitlabAccount() {
|
async addGitlabAccount() {
|
||||||
try {
|
try {
|
||||||
const { serverUrl, applicationId } = await store.dispatch('modal/open', { type: 'gitlabAccount' });
|
const { serverUrl, applicationId, applicationSecret } = await store.dispatch('modal/open', { type: 'gitlabAccount' });
|
||||||
await gitlabHelper.addAccount(serverUrl, applicationId);
|
await gitlabHelper.addAccount(serverUrl, applicationId, applicationSecret);
|
||||||
} catch (e) { /* cancel */ }
|
} catch (e) { /* cancel */ }
|
||||||
},
|
},
|
||||||
async addGiteaAccount() {
|
async addGiteaAccount() {
|
||||||
|
|
|
@ -239,8 +239,8 @@ export default {
|
||||||
},
|
},
|
||||||
async addGitlabAccount() {
|
async addGitlabAccount() {
|
||||||
try {
|
try {
|
||||||
const { serverUrl, applicationId } = await store.dispatch('modal/open', { type: 'gitlabAccount' });
|
const { serverUrl, applicationId, applicationSecret } = await store.dispatch('modal/open', { type: 'gitlabAccount' });
|
||||||
await gitlabHelper.addAccount(serverUrl, applicationId);
|
await gitlabHelper.addAccount(serverUrl, applicationId, applicationSecret);
|
||||||
} catch (e) { /* cancel */ }
|
} catch (e) { /* cancel */ }
|
||||||
},
|
},
|
||||||
async addGiteaAccount() {
|
async addGiteaAccount() {
|
||||||
|
|
|
@ -85,8 +85,8 @@ export default {
|
||||||
},
|
},
|
||||||
async addGitlabWorkspace() {
|
async addGitlabWorkspace() {
|
||||||
try {
|
try {
|
||||||
const { serverUrl, applicationId } = await store.dispatch('modal/open', { type: 'gitlabAccount' });
|
const { serverUrl, applicationId, applicationSecret } = await store.dispatch('modal/open', { type: 'gitlabAccount' });
|
||||||
const token = await gitlabHelper.addAccount(serverUrl, applicationId);
|
const token = await gitlabHelper.addAccount(serverUrl, applicationId, applicationSecret);
|
||||||
store.dispatch('modal/open', {
|
store.dispatch('modal/open', {
|
||||||
type: 'gitlabWorkspace',
|
type: 'gitlabWorkspace',
|
||||||
token,
|
token,
|
||||||
|
|
|
@ -248,8 +248,8 @@ export default {
|
||||||
},
|
},
|
||||||
async addGitlabAccount() {
|
async addGitlabAccount() {
|
||||||
try {
|
try {
|
||||||
const { serverUrl, applicationId } = await store.dispatch('modal/open', { type: 'gitlabAccount' });
|
const { serverUrl, applicationId, applicationSecret } = await store.dispatch('modal/open', { type: 'gitlabAccount' });
|
||||||
await gitlabHelper.addAccount(serverUrl, applicationId);
|
await gitlabHelper.addAccount(serverUrl, applicationId, applicationSecret);
|
||||||
} catch (e) { /* cancel */ }
|
} catch (e) { /* cancel */ }
|
||||||
},
|
},
|
||||||
async addGiteaAccount() {
|
async addGiteaAccount() {
|
||||||
|
|
|
@ -18,6 +18,9 @@
|
||||||
</form-entry>
|
</form-entry>
|
||||||
<form-entry label="Application ID" error="applicationId">
|
<form-entry label="Application ID" error="applicationId">
|
||||||
<input slot="field" class="textfield" type="text" v-model.trim="applicationId" @keydown.enter="resolve()">
|
<input slot="field" class="textfield" type="text" v-model.trim="applicationId" @keydown.enter="resolve()">
|
||||||
|
</form-entry>
|
||||||
|
<form-entry label="Application Secret" error="applicationSecret">
|
||||||
|
<input slot="field" class="textfield" type="text" v-model.trim="applicationSecret" @keydown.enter="resolve()">
|
||||||
<div class="form-entry__info">
|
<div class="form-entry__info">
|
||||||
您必须使用重定向url <b>{{redirectUrl}}</b>配置OAuth2应用程序
|
您必须使用重定向url <b>{{redirectUrl}}</b>配置OAuth2应用程序
|
||||||
</div>
|
</div>
|
||||||
|
@ -47,6 +50,7 @@ export default modalTemplate({
|
||||||
computedLocalSettings: {
|
computedLocalSettings: {
|
||||||
serverUrl: 'gitlabServerUrl',
|
serverUrl: 'gitlabServerUrl',
|
||||||
applicationId: 'gitlabApplicationId',
|
applicationId: 'gitlabApplicationId',
|
||||||
|
applicationSecret: 'gitlabApplicationSecret',
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
httpAppUrl() {
|
httpAppUrl() {
|
||||||
|
@ -78,7 +82,10 @@ export default modalTemplate({
|
||||||
if (!this.applicationId) {
|
if (!this.applicationId) {
|
||||||
this.setError('applicationId');
|
this.setError('applicationId');
|
||||||
}
|
}
|
||||||
if (serverUrl && this.applicationId) {
|
if (!this.applicationSecret) {
|
||||||
|
this.setError('applicationSecret');
|
||||||
|
}
|
||||||
|
if (serverUrl && this.applicationId && this.applicationSecret) {
|
||||||
const parsedUrl = serverUrl.match(/^(http[s]?:\/\/[^/]+)/);
|
const parsedUrl = serverUrl.match(/^(http[s]?:\/\/[^/]+)/);
|
||||||
if (!parsedUrl) {
|
if (!parsedUrl) {
|
||||||
this.setError('serverUrl');
|
this.setError('serverUrl');
|
||||||
|
@ -86,6 +93,7 @@ export default modalTemplate({
|
||||||
this.config.resolve({
|
this.config.resolve({
|
||||||
serverUrl: parsedUrl[1],
|
serverUrl: parsedUrl[1],
|
||||||
applicationId: this.applicationId,
|
applicationId: this.applicationId,
|
||||||
|
applicationSecret: this.applicationSecret,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ export default () => ({
|
||||||
giteePublishTemplate: 'jekyllSite',
|
giteePublishTemplate: 'jekyllSite',
|
||||||
gitlabServerUrl: '',
|
gitlabServerUrl: '',
|
||||||
gitlabApplicationId: '',
|
gitlabApplicationId: '',
|
||||||
|
gitlabApplicationSecret: '',
|
||||||
gitlabProjectUrl: '',
|
gitlabProjectUrl: '',
|
||||||
gitlabWorkspaceProjectUrl: '',
|
gitlabWorkspaceProjectUrl: '',
|
||||||
gitlabPublishTemplate: 'plainText',
|
gitlabPublishTemplate: 'plainText',
|
||||||
|
|
|
@ -75,11 +75,11 @@ export default new Provider({
|
||||||
const sub = workspace ? workspace.sub : utils.queryParams.sub;
|
const sub = workspace ? workspace.sub : utils.queryParams.sub;
|
||||||
let token = store.getters['data/gitlabTokensBySub'][sub];
|
let token = store.getters['data/gitlabTokensBySub'][sub];
|
||||||
if (!token) {
|
if (!token) {
|
||||||
const { applicationId } = await store.dispatch('modal/open', {
|
const { applicationId, applicationSecret } = await store.dispatch('modal/open', {
|
||||||
type: 'gitlabAccount',
|
type: 'gitlabAccount',
|
||||||
forceServerUrl: serverUrl,
|
forceServerUrl: serverUrl,
|
||||||
});
|
});
|
||||||
token = await gitlabHelper.addAccount(serverUrl, applicationId, sub);
|
token = await gitlabHelper.addAccount(serverUrl, applicationId, applicationSecret, sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!workspace) {
|
if (!workspace) {
|
||||||
|
|
|
@ -3,6 +3,9 @@ import networkSvc from '../../networkSvc';
|
||||||
import store from '../../../store';
|
import store from '../../../store';
|
||||||
import userSvc from '../../userSvc';
|
import userSvc from '../../userSvc';
|
||||||
import badgeSvc from '../../badgeSvc';
|
import badgeSvc from '../../badgeSvc';
|
||||||
|
import constants from '../../../data/constants';
|
||||||
|
|
||||||
|
const tokenExpirationMargin = 5 * 60 * 1000;
|
||||||
|
|
||||||
const request = ({ accessToken, serverUrl }, options) => networkSvc.request({
|
const request = ({ accessToken, serverUrl }, options) => networkSvc.request({
|
||||||
...options,
|
...options,
|
||||||
|
@ -50,34 +53,90 @@ export default {
|
||||||
/**
|
/**
|
||||||
* https://docs.gitlab.com/ee/api/oauth2.html
|
* https://docs.gitlab.com/ee/api/oauth2.html
|
||||||
*/
|
*/
|
||||||
async startOauth2(serverUrl, applicationId, sub = null, silent = false) {
|
async startOauth2(
|
||||||
|
serverUrl, applicationId, applicationSecret,
|
||||||
|
sub = null, silent = false, refreshToken,
|
||||||
|
) {
|
||||||
let apiUrl = serverUrl;
|
let apiUrl = serverUrl;
|
||||||
let clientId = applicationId;
|
let clientId = applicationId;
|
||||||
// 获取gitea配置的参数
|
let useServerConf = false;
|
||||||
|
// 获取gitlab配置的参数
|
||||||
await networkSvc.getServerConf();
|
await networkSvc.getServerConf();
|
||||||
const confClientId = store.getters['data/serverConf'].gitlabClientId;
|
const confClientId = store.getters['data/serverConf'].gitlabClientId;
|
||||||
const confServerUrl = store.getters['data/serverConf'].gitlabUrl;
|
const confServerUrl = store.getters['data/serverConf'].gitlabUrl;
|
||||||
// 存在gitea配置则使用后端配置
|
// 存在gitlab配置则使用后端配置
|
||||||
if (confClientId && confServerUrl) {
|
if (confClientId && confServerUrl) {
|
||||||
apiUrl = confServerUrl;
|
apiUrl = confServerUrl;
|
||||||
clientId = confClientId;
|
clientId = confClientId;
|
||||||
|
useServerConf = true;
|
||||||
|
}
|
||||||
|
let tokenBody;
|
||||||
|
if (!silent) {
|
||||||
|
// Get an OAuth2 code
|
||||||
|
const { code } = await networkSvc.startOauth2(
|
||||||
|
`${apiUrl}/oauth/authorize`,
|
||||||
|
{
|
||||||
|
client_id: clientId,
|
||||||
|
response_type: 'code',
|
||||||
|
redirect_uri: constants.oauth2RedirectUri,
|
||||||
|
},
|
||||||
|
silent,
|
||||||
|
);
|
||||||
|
if (useServerConf) {
|
||||||
|
tokenBody = (await networkSvc.request({
|
||||||
|
method: 'GET',
|
||||||
|
url: 'oauth2/gitlabToken',
|
||||||
|
params: {
|
||||||
|
code,
|
||||||
|
grant_type: 'authorization_code',
|
||||||
|
redirect_uri: constants.oauth2RedirectUri,
|
||||||
|
},
|
||||||
|
})).body;
|
||||||
|
} else {
|
||||||
|
// Exchange code with token
|
||||||
|
tokenBody = (await networkSvc.request({
|
||||||
|
method: 'POST',
|
||||||
|
url: `${apiUrl}/oauth/token`,
|
||||||
|
params: {
|
||||||
|
client_id: clientId,
|
||||||
|
client_secret: applicationSecret,
|
||||||
|
code,
|
||||||
|
grant_type: 'authorization_code',
|
||||||
|
redirect_uri: constants.oauth2RedirectUri,
|
||||||
|
},
|
||||||
|
})).body;
|
||||||
|
}
|
||||||
|
} else if (useServerConf) {
|
||||||
|
tokenBody = (await networkSvc.request({
|
||||||
|
method: 'GET',
|
||||||
|
url: 'oauth2/gitlabToken',
|
||||||
|
params: {
|
||||||
|
refresh_token: refreshToken,
|
||||||
|
grant_type: 'refresh_token',
|
||||||
|
redirect_uri: constants.oauth2RedirectUri,
|
||||||
|
},
|
||||||
|
})).body;
|
||||||
|
} else {
|
||||||
|
// Exchange refreshToken with token
|
||||||
|
tokenBody = (await networkSvc.request({
|
||||||
|
method: 'POST',
|
||||||
|
url: `${apiUrl}/oauth/token`,
|
||||||
|
body: {
|
||||||
|
client_id: clientId,
|
||||||
|
client_secret: applicationSecret,
|
||||||
|
refresh_token: refreshToken,
|
||||||
|
grant_type: 'refresh_token',
|
||||||
|
redirect_uri: constants.oauth2RedirectUri,
|
||||||
|
},
|
||||||
|
})).body;
|
||||||
}
|
}
|
||||||
// Get an OAuth2 code
|
|
||||||
const { accessToken } = await networkSvc.startOauth2(
|
|
||||||
`${apiUrl}/oauth/authorize`,
|
|
||||||
{
|
|
||||||
client_id: clientId,
|
|
||||||
response_type: 'token',
|
|
||||||
scope: 'api',
|
|
||||||
},
|
|
||||||
silent,
|
|
||||||
);
|
|
||||||
|
|
||||||
|
const accessToken = tokenBody.access_token;
|
||||||
// Call the user info endpoint
|
// Call the user info endpoint
|
||||||
const user = await request({ accessToken, serverUrl }, {
|
const user = await request({ accessToken, serverUrl: apiUrl }, {
|
||||||
url: 'user',
|
url: 'user',
|
||||||
});
|
});
|
||||||
const uniqueSub = `${serverUrl}/${user.id}`;
|
const uniqueSub = `${apiUrl}/${user.id}`;
|
||||||
userSvc.addUserInfo({
|
userSvc.addUserInfo({
|
||||||
id: `${subPrefix}:${uniqueSub}`,
|
id: `${subPrefix}:${uniqueSub}`,
|
||||||
name: user.username,
|
name: user.username,
|
||||||
|
@ -89,11 +148,17 @@ export default {
|
||||||
throw new Error('GitLab account ID not expected.');
|
throw new Error('GitLab account ID not expected.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const oldToken = store.getters['data/gitlabTokensBySub'][uniqueSub];
|
||||||
// Build token object including scopes and sub
|
// Build token object including scopes and sub
|
||||||
const token = {
|
const token = {
|
||||||
accessToken,
|
accessToken,
|
||||||
name: user.username,
|
name: user.username,
|
||||||
serverUrl,
|
applicationId: clientId,
|
||||||
|
applicationSecret,
|
||||||
|
imgStorages: oldToken && oldToken.imgStorages,
|
||||||
|
refreshToken: tokenBody.refresh_token,
|
||||||
|
expiresOn: Date.now() + ((tokenBody.expires_in || 7200) * 1000),
|
||||||
|
serverUrl: apiUrl,
|
||||||
sub: uniqueSub,
|
sub: uniqueSub,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -101,12 +166,58 @@ export default {
|
||||||
store.dispatch('data/addGitlabToken', token);
|
store.dispatch('data/addGitlabToken', token);
|
||||||
return token;
|
return token;
|
||||||
},
|
},
|
||||||
async addAccount(serverUrl, applicationId, sub = null) {
|
async addAccount(serverUrl, applicationId, applicationSecret, sub = null) {
|
||||||
const token = await this.startOauth2(serverUrl, applicationId, sub);
|
const token = await this.startOauth2(serverUrl, applicationId, applicationSecret, sub);
|
||||||
badgeSvc.addBadge('addGitLabAccount');
|
badgeSvc.addBadge('addGitLabAccount');
|
||||||
return token;
|
return token;
|
||||||
},
|
},
|
||||||
|
// 刷新token
|
||||||
|
async refreshToken(token) {
|
||||||
|
const {
|
||||||
|
serverUrl,
|
||||||
|
applicationId,
|
||||||
|
applicationSecret,
|
||||||
|
sub,
|
||||||
|
} = token;
|
||||||
|
const lastToken = store.getters['data/gitlabTokensBySub'][sub];
|
||||||
|
// 兼容旧的没有过期时间
|
||||||
|
if (!lastToken.expiresOn || !lastToken.refreshToken) {
|
||||||
|
await store.dispatch('modal/open', {
|
||||||
|
type: 'providerRedirection',
|
||||||
|
name: 'Gitlab',
|
||||||
|
});
|
||||||
|
return this.startOauth2(serverUrl, applicationId, applicationSecret, sub);
|
||||||
|
}
|
||||||
|
// lastToken is not expired
|
||||||
|
if (lastToken.expiresOn > Date.now() + tokenExpirationMargin) {
|
||||||
|
return lastToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
// existing token is about to expire.
|
||||||
|
// Try to get a new token in background
|
||||||
|
try {
|
||||||
|
return await this.startOauth2(
|
||||||
|
serverUrl, applicationId, applicationSecret,
|
||||||
|
sub, true, lastToken.refreshToken,
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
// If it fails try to popup a window
|
||||||
|
if (store.state.offline) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
await store.dispatch('modal/open', {
|
||||||
|
type: 'providerRedirection',
|
||||||
|
name: 'Gitlab',
|
||||||
|
});
|
||||||
|
return this.startOauth2(serverUrl, applicationId, applicationSecret, sub);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 带刷新token
|
||||||
|
async requestWithRefreshToken(token, options) {
|
||||||
|
const refreshedToken = await this.refreshToken(token);
|
||||||
|
const result = await request(refreshedToken, options);
|
||||||
|
return result;
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* https://docs.gitlab.com/ee/api/projects.html#get-single-project
|
* https://docs.gitlab.com/ee/api/projects.html#get-single-project
|
||||||
*/
|
*/
|
||||||
|
@ -114,8 +225,7 @@ export default {
|
||||||
if (projectId) {
|
if (projectId) {
|
||||||
return projectId;
|
return projectId;
|
||||||
}
|
}
|
||||||
|
const project = await this.requestWithRefreshToken(token, {
|
||||||
const project = await request(token, {
|
|
||||||
url: `projects/${encodeURIComponent(projectPath)}`,
|
url: `projects/${encodeURIComponent(projectPath)}`,
|
||||||
});
|
});
|
||||||
return project.id;
|
return project.id;
|
||||||
|
@ -129,7 +239,7 @@ export default {
|
||||||
projectId,
|
projectId,
|
||||||
branch,
|
branch,
|
||||||
}) {
|
}) {
|
||||||
return request(token, {
|
return this.requestWithRefreshToken(token, {
|
||||||
url: `projects/${encodeURIComponent(projectId)}/repository/tree`,
|
url: `projects/${encodeURIComponent(projectId)}/repository/tree`,
|
||||||
params: {
|
params: {
|
||||||
ref: branch,
|
ref: branch,
|
||||||
|
@ -148,7 +258,7 @@ export default {
|
||||||
branch,
|
branch,
|
||||||
path,
|
path,
|
||||||
}) {
|
}) {
|
||||||
return request(token, {
|
return this.requestWithRefreshToken(token, {
|
||||||
url: `projects/${encodeURIComponent(projectId)}/repository/commits`,
|
url: `projects/${encodeURIComponent(projectId)}/repository/commits`,
|
||||||
params: {
|
params: {
|
||||||
ref_name: branch,
|
ref_name: branch,
|
||||||
|
@ -175,7 +285,7 @@ export default {
|
||||||
if (isImg && typeof content !== 'string') {
|
if (isImg && typeof content !== 'string') {
|
||||||
uploadContent = await utils.encodeFiletoBase64(content);
|
uploadContent = await utils.encodeFiletoBase64(content);
|
||||||
}
|
}
|
||||||
return request(token, {
|
return this.requestWithRefreshToken(token, {
|
||||||
method: sha ? 'PUT' : 'POST',
|
method: sha ? 'PUT' : 'POST',
|
||||||
url: `projects/${encodeURIComponent(projectId)}/repository/files/${encodeURIComponent(path)}`,
|
url: `projects/${encodeURIComponent(projectId)}/repository/files/${encodeURIComponent(path)}`,
|
||||||
body: {
|
body: {
|
||||||
|
@ -198,7 +308,7 @@ export default {
|
||||||
path,
|
path,
|
||||||
sha,
|
sha,
|
||||||
}) {
|
}) {
|
||||||
return request(token, {
|
return this.requestWithRefreshToken(token, {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
url: `projects/${encodeURIComponent(projectId)}/repository/files/${encodeURIComponent(path)}`,
|
url: `projects/${encodeURIComponent(projectId)}/repository/files/${encodeURIComponent(path)}`,
|
||||||
body: {
|
body: {
|
||||||
|
@ -219,7 +329,7 @@ export default {
|
||||||
path,
|
path,
|
||||||
isImg,
|
isImg,
|
||||||
}) {
|
}) {
|
||||||
const res = await request(token, {
|
const res = await this.requestWithRefreshToken(token, {
|
||||||
url: `projects/${encodeURIComponent(projectId)}/repository/files/${encodeURIComponent(path)}`,
|
url: `projects/${encodeURIComponent(projectId)}/repository/files/${encodeURIComponent(path)}`,
|
||||||
params: { ref: branch },
|
params: { ref: branch },
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue
Block a user