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