gitee gitea 支持bugfix
This commit is contained in:
parent
cb58d05147
commit
198c8cb647
@ -8,5 +8,5 @@ module.exports = merge(prodEnv, {
|
|||||||
GITHUB_CLIENT_SECRET: '"80df676597abded1450926861965cc3f9bead6a0"',
|
GITHUB_CLIENT_SECRET: '"80df676597abded1450926861965cc3f9bead6a0"',
|
||||||
GITEE_CLIENT_ID: '"925ba7c78b85dec984f7877e4aca5cab10ae333c6d68e761bdb0b9dfb8f55672"',
|
GITEE_CLIENT_ID: '"925ba7c78b85dec984f7877e4aca5cab10ae333c6d68e761bdb0b9dfb8f55672"',
|
||||||
GITEE_CLIENT_SECRET: '"f05731066e42d307339dc8ebbb037a103881dafc7207a359a393b87749f1c562"',
|
GITEE_CLIENT_SECRET: '"f05731066e42d307339dc8ebbb037a103881dafc7207a359a393b87749f1c562"',
|
||||||
GITEE_CALLBACK: '"http://test.local.com/oauth2/callback"'
|
CLIENT_ID: '"thF3qCGLN39OtafjGnqHyj6n02WwE6xD"',
|
||||||
})
|
})
|
@ -10,7 +10,6 @@ const githubClientId = process.env.GITHUB_CLIENT_ID;
|
|||||||
const githubClientSecret = process.env.GITHUB_CLIENT_SECRET;
|
const githubClientSecret = process.env.GITHUB_CLIENT_SECRET;
|
||||||
const giteeClientId = process.env.GITEE_CLIENT_ID;
|
const giteeClientId = process.env.GITEE_CLIENT_ID;
|
||||||
const giteeClientSecret = process.env.GITEE_CLIENT_SECRET;
|
const giteeClientSecret = process.env.GITEE_CLIENT_SECRET;
|
||||||
const giteeCallback = process.env.GITEE_CALLBACK;
|
|
||||||
const googleClientId = process.env.GOOGLE_CLIENT_ID;
|
const googleClientId = process.env.GOOGLE_CLIENT_ID;
|
||||||
const googleApiKey = process.env.GOOGLE_API_KEY;
|
const googleApiKey = process.env.GOOGLE_API_KEY;
|
||||||
const wordpressClientId = process.env.WORDPRESS_CLIENT_ID;
|
const wordpressClientId = process.env.WORDPRESS_CLIENT_ID;
|
||||||
@ -27,7 +26,6 @@ exports.values = {
|
|||||||
githubClientSecret,
|
githubClientSecret,
|
||||||
giteeClientId,
|
giteeClientId,
|
||||||
giteeClientSecret,
|
giteeClientSecret,
|
||||||
giteeCallback,
|
|
||||||
googleClientId,
|
googleClientId,
|
||||||
googleApiKey,
|
googleApiKey,
|
||||||
wordpressClientId,
|
wordpressClientId,
|
||||||
|
@ -9,17 +9,17 @@
|
|||||||
</select>
|
</select>
|
||||||
</p>
|
</p>
|
||||||
<p v-if="!historyContext">同步 <b>{{currentFileName}}</b> 以启用修订历史 或者 <a href="javascript:void(0)" @click="signin">登录 Google</a> 以同步您的主工作区。</p>
|
<p v-if="!historyContext">同步 <b>{{currentFileName}}</b> 以启用修订历史 或者 <a href="javascript:void(0)" @click="signin">登录 Google</a> 以同步您的主工作区。</p>
|
||||||
<p v-else-if="loading">Loading history…</p>
|
<p v-else-if="loading">历史版本加载中…</p>
|
||||||
<p v-else-if="!revisionsWithSpacer.length"><b>{{currentFileName}}</b> has no history.</p>
|
<p v-else-if="!revisionsWithSpacer.length"><b>{{currentFileName}}</b> 没有历史版本.</p>
|
||||||
<div class="menu-entry menu-entry--info flex flex--row flex--align-center" v-else>
|
<div class="menu-entry menu-entry--info flex flex--row flex--align-center" v-else>
|
||||||
<div class="menu-entry__icon menu-entry__icon--image">
|
<div class="menu-entry__icon menu-entry__icon--image">
|
||||||
<icon-provider :provider-id="syncLocation.providerId"></icon-provider>
|
<icon-provider :provider-id="syncLocation.providerId"></icon-provider>
|
||||||
</div>
|
</div>
|
||||||
<span v-if="syncLocation.url">
|
<span v-if="syncLocation.url">
|
||||||
The following revisions are stored in <a :href="syncLocation.url" target="_blank">{{ syncLocationProviderName }}</a>.
|
下面的历史版本存储在 <a :href="syncLocation.url" target="_blank">{{ syncLocationProviderName }}</a>.
|
||||||
</span>
|
</span>
|
||||||
<span v-else>
|
<span v-else>
|
||||||
The following revisions are stored in {{ syncLocationProviderName }}.
|
下面的历史版本存储在 {{ syncLocationProviderName }}.
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -39,7 +39,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="history__spacer history__spacer--last" v-if="revisions.length"></div>
|
<div class="history__spacer history__spacer--last" v-if="revisions.length"></div>
|
||||||
<div class="flex flex--row flex--end" v-if="showMoreButton">
|
<div class="flex flex--row flex--end" v-if="showMoreButton">
|
||||||
<button class="history__button button" @click="showMore">More</button>
|
<button class="history__button button" @click="showMore">更多</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -15,7 +15,7 @@ StackEdit 将您的文件存储在您的浏览器中,这意味着您的所有
|
|||||||
|
|
||||||
您的所有文件和文件夹在文件资源管理器中都显示为树。您可以通过单击树中的文件从一个文件切换到另一个文件。
|
您的所有文件和文件夹在文件资源管理器中都显示为树。您可以通过单击树中的文件从一个文件切换到另一个文件。
|
||||||
|
|
||||||
##重命名文件
|
## 重命名文件
|
||||||
|
|
||||||
您可以通过单击导航栏中的文件名或单击文件资源管理器中的**重命名**按钮来重命名当前文件。
|
您可以通过单击导航栏中的文件名或单击文件资源管理器中的**重命名**按钮来重命名当前文件。
|
||||||
|
|
||||||
|
@ -135,17 +135,24 @@ export default new Provider({
|
|||||||
token,
|
token,
|
||||||
});
|
});
|
||||||
|
|
||||||
return entries.map((entry) => {
|
return entries.map(({
|
||||||
const email = entry.author_email || entry.committer_email;
|
author,
|
||||||
const sub = `${giteaHelper.subPrefix}:${token.serverUrl}/${email}`;
|
committer,
|
||||||
userSvc.addUserInfo({
|
commit,
|
||||||
id: sub,
|
sha,
|
||||||
name: entry.author_name || entry.committer_name,
|
}) => {
|
||||||
imageUrl: '',
|
let user;
|
||||||
});
|
if (author && author.login) {
|
||||||
const date = entry.authored_date || entry.committed_date || 1;
|
user = author;
|
||||||
|
} else if (committer && committer.login) {
|
||||||
|
user = committer;
|
||||||
|
}
|
||||||
|
const sub = `${giteaHelper.subPrefix}:${user.login}`;
|
||||||
|
userSvc.addUserInfo({ id: sub, name: user.login, imageUrl: user.avatar_url });
|
||||||
|
const date = (commit.author && commit.author.date)
|
||||||
|
|| (commit.committer && commit.committer.date);
|
||||||
return {
|
return {
|
||||||
id: entry.id,
|
id: sha,
|
||||||
sub,
|
sub,
|
||||||
created: date ? new Date(date).getTime() : 1,
|
created: date ? new Date(date).getTime() : 1,
|
||||||
};
|
};
|
||||||
|
@ -251,19 +251,27 @@ export default new Provider({
|
|||||||
path: getAbsolutePath({ id: fileSyncDataId }),
|
path: getAbsolutePath({ id: fileSyncDataId }),
|
||||||
});
|
});
|
||||||
|
|
||||||
return entries.map((entry) => {
|
return entries.map(({
|
||||||
const email = entry.author_email || entry.committer_email;
|
author,
|
||||||
const sub = `${giteaHelper.subPrefix}:${token.serverUrl}/${email}`;
|
committer,
|
||||||
userSvc.addUserInfo({
|
commit,
|
||||||
id: sub,
|
sha,
|
||||||
name: entry.author_name || entry.committer_name,
|
}) => {
|
||||||
imageUrl: '', // No way to get user's avatar url...
|
let user;
|
||||||
});
|
if (author && author.login) {
|
||||||
const date = entry.authored_date || entry.committed_date || 1;
|
user = author;
|
||||||
|
} else if (committer && committer.login) {
|
||||||
|
user = committer;
|
||||||
|
}
|
||||||
|
const sub = `${giteaHelper.subPrefix}:${user.login}`;
|
||||||
|
userSvc.addUserInfo({ id: sub, name: user.login, imageUrl: user.avatar_url });
|
||||||
|
const date = (commit.author && commit.author.date)
|
||||||
|
|| (commit.committer && commit.committer.date)
|
||||||
|
|| 1;
|
||||||
return {
|
return {
|
||||||
id: entry.id,
|
id: sha,
|
||||||
sub,
|
sub,
|
||||||
created: date ? new Date(date).getTime() : 1,
|
created: new Date(date).getTime(),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -135,6 +135,9 @@ export default new Provider({
|
|||||||
user = committer;
|
user = committer;
|
||||||
}
|
}
|
||||||
const sub = `${giteeHelper.subPrefix}:${user.login}`;
|
const sub = `${giteeHelper.subPrefix}:${user.login}`;
|
||||||
|
if (user.avatar_url && user.avatar_url.endsWith('.png')) {
|
||||||
|
user.avatar_url = `${user.avatar_url}!avatar60`;
|
||||||
|
}
|
||||||
userSvc.addUserInfo({ id: sub, name: user.login, imageUrl: user.avatar_url });
|
userSvc.addUserInfo({ id: sub, name: user.login, imageUrl: user.avatar_url });
|
||||||
const date = (commit.author && commit.author.date)
|
const date = (commit.author && commit.author.date)
|
||||||
|| (commit.committer && commit.committer.date);
|
|| (commit.committer && commit.committer.date);
|
||||||
|
@ -249,6 +249,9 @@ export default new Provider({
|
|||||||
user = committer;
|
user = committer;
|
||||||
}
|
}
|
||||||
const sub = `${giteeHelper.subPrefix}:${user.login}`;
|
const sub = `${giteeHelper.subPrefix}:${user.login}`;
|
||||||
|
if (user.avatar_url && user.avatar_url.endsWith('.png')) {
|
||||||
|
user.avatar_url = `${user.avatar_url}!avatar60`;
|
||||||
|
}
|
||||||
userSvc.addUserInfo({ id: sub, name: user.login, imageUrl: user.avatar_url });
|
userSvc.addUserInfo({ id: sub, name: user.login, imageUrl: user.avatar_url });
|
||||||
const date = (commit.author && commit.author.date)
|
const date = (commit.author && commit.author.date)
|
||||||
|| (commit.committer && commit.committer.date)
|
|| (commit.committer && commit.committer.date)
|
||||||
|
@ -5,6 +5,8 @@ import userSvc from '../../userSvc';
|
|||||||
import badgeSvc from '../../badgeSvc';
|
import badgeSvc from '../../badgeSvc';
|
||||||
import constants from '../../../data/constants';
|
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,
|
||||||
url: `${serverUrl}/api/v1/${options.url}`,
|
url: `${serverUrl}/api/v1/${options.url}`,
|
||||||
@ -51,30 +53,50 @@ export default {
|
|||||||
/**
|
/**
|
||||||
* https://docs.gitea.io/en-us/oauth2-provider/
|
* https://docs.gitea.io/en-us/oauth2-provider/
|
||||||
*/
|
*/
|
||||||
async startOauth2(serverUrl, applicationId, applicationSecret, sub = null, silent = false) {
|
async startOauth2(
|
||||||
// Get an OAuth2 code
|
serverUrl, applicationId, applicationSecret,
|
||||||
const { code } = await networkSvc.startOauth2(
|
sub = null, silent = false, refreshToken,
|
||||||
`${serverUrl}/login/oauth/authorize`,
|
) {
|
||||||
{
|
let tokenBody;
|
||||||
client_id: applicationId,
|
if (!silent) {
|
||||||
response_type: 'code',
|
// Get an OAuth2 code
|
||||||
redirect_uri: constants.oauth2RedirectUri,
|
const { code } = await networkSvc.startOauth2(
|
||||||
},
|
`${serverUrl}/login/oauth/authorize`,
|
||||||
silent,
|
{
|
||||||
);
|
client_id: applicationId,
|
||||||
|
response_type: 'code',
|
||||||
|
redirect_uri: constants.oauth2RedirectUri,
|
||||||
|
},
|
||||||
|
silent,
|
||||||
|
);
|
||||||
|
// Exchange code with token
|
||||||
|
tokenBody = (await networkSvc.request({
|
||||||
|
method: 'POST',
|
||||||
|
url: `${serverUrl}/login/oauth/access_token`,
|
||||||
|
body: {
|
||||||
|
client_id: applicationId,
|
||||||
|
client_secret: applicationSecret,
|
||||||
|
code,
|
||||||
|
grant_type: 'authorization_code',
|
||||||
|
redirect_uri: constants.oauth2RedirectUri,
|
||||||
|
},
|
||||||
|
})).body;
|
||||||
|
} else {
|
||||||
|
// Exchange refreshToken with token
|
||||||
|
tokenBody = (await networkSvc.request({
|
||||||
|
method: 'POST',
|
||||||
|
url: `${serverUrl}/login/oauth/access_token`,
|
||||||
|
body: {
|
||||||
|
client_id: applicationId,
|
||||||
|
client_secret: applicationSecret,
|
||||||
|
refresh_token: refreshToken,
|
||||||
|
grant_type: 'refresh_token',
|
||||||
|
redirect_uri: constants.oauth2RedirectUri,
|
||||||
|
},
|
||||||
|
})).body;
|
||||||
|
}
|
||||||
|
|
||||||
// Exchange code with token
|
const accessToken = tokenBody.access_token;
|
||||||
const accessToken = (await networkSvc.request({
|
|
||||||
method: 'POST',
|
|
||||||
url: `${serverUrl}/login/oauth/access_token`,
|
|
||||||
body: {
|
|
||||||
client_id: applicationId,
|
|
||||||
client_secret: applicationSecret,
|
|
||||||
code,
|
|
||||||
grant_type: 'authorization_code',
|
|
||||||
redirect_uri: constants.oauth2RedirectUri,
|
|
||||||
},
|
|
||||||
})).body.access_token;
|
|
||||||
|
|
||||||
// Call the user info endpoint
|
// Call the user info endpoint
|
||||||
const user = await request({ accessToken, serverUrl }, {
|
const user = await request({ accessToken, serverUrl }, {
|
||||||
@ -96,6 +118,8 @@ export default {
|
|||||||
const token = {
|
const token = {
|
||||||
accessToken,
|
accessToken,
|
||||||
name: user.username,
|
name: user.username,
|
||||||
|
refreshToken: tokenBody.refresh_token,
|
||||||
|
expiresOn: Date.now() + (tokenBody.expires_in * 1000),
|
||||||
serverUrl,
|
serverUrl,
|
||||||
sub: uniqueSub,
|
sub: uniqueSub,
|
||||||
};
|
};
|
||||||
@ -104,6 +128,47 @@ export default {
|
|||||||
store.dispatch('data/addGiteaToken', token);
|
store.dispatch('data/addGiteaToken', token);
|
||||||
return token;
|
return token;
|
||||||
},
|
},
|
||||||
|
// 刷新token
|
||||||
|
async refreshToken(token) {
|
||||||
|
const {
|
||||||
|
serverUrl,
|
||||||
|
applicationId,
|
||||||
|
applicationSecret,
|
||||||
|
sub,
|
||||||
|
} = token;
|
||||||
|
const lastToken = store.getters['data/giteaTokensBySub'][sub];
|
||||||
|
// 兼容旧的没有过期时间
|
||||||
|
if (!lastToken.expiresOn) {
|
||||||
|
await store.dispatch('modal/open', {
|
||||||
|
type: 'providerRedirection',
|
||||||
|
name: 'Gitea',
|
||||||
|
});
|
||||||
|
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: 'Gitea',
|
||||||
|
});
|
||||||
|
return this.startOauth2(serverUrl, applicationId, applicationSecret, sub);
|
||||||
|
}
|
||||||
|
},
|
||||||
async addAccount(serverUrl, applicationId, applicationSecret, sub = null) {
|
async addAccount(serverUrl, applicationId, applicationSecret, sub = null) {
|
||||||
const token = await this.startOauth2(serverUrl, applicationId, applicationSecret, sub);
|
const token = await this.startOauth2(serverUrl, applicationId, applicationSecret, sub);
|
||||||
badgeSvc.addBadge('addGiteaAccount');
|
badgeSvc.addBadge('addGiteaAccount');
|
||||||
@ -129,7 +194,8 @@ export default {
|
|||||||
projectId,
|
projectId,
|
||||||
branch,
|
branch,
|
||||||
}) {
|
}) {
|
||||||
return request(token, {
|
const refreshedToken = await this.refreshToken(token);
|
||||||
|
return request(refreshedToken, {
|
||||||
url: `repos/${projectId}/git/trees/${branch}`,
|
url: `repos/${projectId}/git/trees/${branch}`,
|
||||||
params: {
|
params: {
|
||||||
recursive: true,
|
recursive: true,
|
||||||
@ -147,7 +213,8 @@ export default {
|
|||||||
branch,
|
branch,
|
||||||
path,
|
path,
|
||||||
}) {
|
}) {
|
||||||
return request(token, {
|
const refreshedToken = await this.refreshToken(token);
|
||||||
|
return request(refreshedToken, {
|
||||||
url: `repos/${projectId}/commits`,
|
url: `repos/${projectId}/commits`,
|
||||||
params: {
|
params: {
|
||||||
sha: branch,
|
sha: branch,
|
||||||
@ -168,7 +235,8 @@ export default {
|
|||||||
content,
|
content,
|
||||||
sha,
|
sha,
|
||||||
}) {
|
}) {
|
||||||
return request(token, {
|
const refreshedToken = await this.refreshToken(token);
|
||||||
|
return request(refreshedToken, {
|
||||||
method: sha ? 'PUT' : 'POST',
|
method: sha ? 'PUT' : 'POST',
|
||||||
url: `repos/${projectId}/contents/${encodeURIComponent(path)}`,
|
url: `repos/${projectId}/contents/${encodeURIComponent(path)}`,
|
||||||
body: {
|
body: {
|
||||||
@ -190,7 +258,8 @@ export default {
|
|||||||
path,
|
path,
|
||||||
sha,
|
sha,
|
||||||
}) {
|
}) {
|
||||||
return request(token, {
|
const refreshedToken = await this.refreshToken(token);
|
||||||
|
return request(refreshedToken, {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
url: `repos/${projectId}/contents/${encodeURIComponent(path)}`,
|
url: `repos/${projectId}/contents/${encodeURIComponent(path)}`,
|
||||||
body: {
|
body: {
|
||||||
@ -210,7 +279,8 @@ export default {
|
|||||||
branch,
|
branch,
|
||||||
path,
|
path,
|
||||||
}) {
|
}) {
|
||||||
const { sha, content } = await request(token, {
|
const refreshedToken = await this.refreshToken(token);
|
||||||
|
const { sha, content } = await request(refreshedToken, {
|
||||||
url: `repos/${projectId}/contents/${encodeURIComponent(path)}`,
|
url: `repos/${projectId}/contents/${encodeURIComponent(path)}`,
|
||||||
params: { ref: branch },
|
params: { ref: branch },
|
||||||
});
|
});
|
||||||
|
@ -139,7 +139,7 @@ export default {
|
|||||||
return this.startOauth2();
|
return this.startOauth2();
|
||||||
}
|
}
|
||||||
// lastToken is not expired
|
// lastToken is not expired
|
||||||
if (lastToken.expiresOn > Date.now() - tokenExpirationMargin) {
|
if (lastToken.expiresOn > Date.now() + tokenExpirationMargin) {
|
||||||
return lastToken;
|
return lastToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,21 +138,21 @@ class RelativeTime {
|
|||||||
const hr = Math.round(min / 60);
|
const hr = Math.round(min / 60);
|
||||||
const day = Math.round(hr / 24);
|
const day = Math.round(hr / 24);
|
||||||
if (ms < 0) {
|
if (ms < 0) {
|
||||||
return 'just now';
|
return '刚刚';
|
||||||
} else if (sec < 45) {
|
} else if (sec < 45) {
|
||||||
return 'just now';
|
return '刚刚';
|
||||||
} else if (sec < 90) {
|
} else if (sec < 90) {
|
||||||
return 'a minute ago';
|
return '1分钟前';
|
||||||
} else if (min < 45) {
|
} else if (min < 45) {
|
||||||
return `${min} minutes ago`;
|
return `${min}分钟前`;
|
||||||
} else if (min < 90) {
|
} else if (min < 90) {
|
||||||
return 'an hour ago';
|
return '1小时前';
|
||||||
} else if (hr < 24) {
|
} else if (hr < 24) {
|
||||||
return `${hr} hours ago`;
|
return `${hr}小时前`;
|
||||||
} else if (hr < 36) {
|
} else if (hr < 36) {
|
||||||
return 'a day ago';
|
return '1天前';
|
||||||
} else if (day < 30) {
|
} else if (day < 30) {
|
||||||
return `${day} days ago`;
|
return `${day}天前`;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user