mirror of
https://github.com/EnixCoda/Gitako.git
synced 2026-03-11 08:54:44 +00:00
refactor: sanitize URL usages
This commit is contained in:
parent
6fde8c1092
commit
9435e9cd52
12 changed files with 909 additions and 745 deletions
|
|
@ -11,7 +11,7 @@
|
|||
"prepare": "husky install",
|
||||
"dev": "VERSION=dev-v$(node scripts/get-version.js) webpack --watch",
|
||||
"dev-safari": "TARGET=safari yarn run dev",
|
||||
"debug-firefox": "web-ext run --source-dir=dist --firefox-profile=firefox-profile --profile-create-if-missing --keep-profile-changes --start-url github.com/EnixCoda/Gitako",
|
||||
"debug-firefox": "web-ext run --source-dir=dist --firefox-profile=firefox-profile --profile-create-if-missing --keep-profile-changes --start-url https://github.com/EnixCoda/Gitako",
|
||||
"analyse-bundle": "ANALYSE= NODE_ENV=production webpack",
|
||||
"postinstall": "node scripts/fix-deps",
|
||||
"build": "VERSION=v$(node scripts/get-version.js) NODE_ENV=production webpack",
|
||||
|
|
@ -89,7 +89,7 @@
|
|||
"typescript": "^4.7.2",
|
||||
"uglifyjs-webpack-plugin": "^2.1.2",
|
||||
"url-loader": "^1.1.2",
|
||||
"web-ext": "^6.8.0",
|
||||
"web-ext": "^7.1.1",
|
||||
"webpack": "^4.29.6",
|
||||
"webpack-bundle-analyzer": "^3.6.0",
|
||||
"webpack-cli": "^3.1.2"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { errors } from 'platforms'
|
||||
import { isEnterprise } from '.'
|
||||
import { is } from '../../utils/is'
|
||||
import { gitakoServiceHost } from '../../utils/networkService'
|
||||
import { continuousLoadPages, getDOM, resolveHeaderLink } from './utils'
|
||||
|
||||
function isAPIRateLimitExceeded(content: JSONValue) {
|
||||
|
|
@ -71,14 +72,14 @@ async function request<T>(
|
|||
throw new Error(`Unknown message content "${message}"`)
|
||||
}
|
||||
|
||||
const API_ENDPOINT = isEnterprise() ? `${window.location.host}/api/v3` : 'api.github.com'
|
||||
const API_ENDPOINT = isEnterprise() ? `${window.location.origin}/api/v3` : 'https://api.github.com'
|
||||
|
||||
export async function getRepoMeta(
|
||||
userName: string,
|
||||
repoName: string,
|
||||
accessToken?: string,
|
||||
): Promise<GitHubAPI.MetaData> {
|
||||
const url = `https://${API_ENDPOINT}/repos/${userName}/${repoName}`
|
||||
const url = `${API_ENDPOINT}/repos/${userName}/${repoName}`
|
||||
return await request(url, { accessToken })
|
||||
}
|
||||
|
||||
|
|
@ -91,8 +92,7 @@ export async function getTreeData(
|
|||
): Promise<GitHubAPI.TreeData> {
|
||||
const search = new URLSearchParams()
|
||||
if (recursive) search.set('recursive', '1')
|
||||
const url =
|
||||
`https://${API_ENDPOINT}/repos/${userName}/${repoName}/git/trees/${branchName}?` + search
|
||||
const url = `${API_ENDPOINT}/repos/${userName}/${repoName}/git/trees/${branchName}?${search}`
|
||||
return await request(url, { accessToken })
|
||||
}
|
||||
|
||||
|
|
@ -102,7 +102,7 @@ export async function getPullRequest(
|
|||
pullId: string,
|
||||
accessToken?: string,
|
||||
): Promise<GitHubAPI.PullData> {
|
||||
const url = `https://${API_ENDPOINT}/repos/${userName}/${repoName}/pulls/${pullId}`
|
||||
const url = `${API_ENDPOINT}/repos/${userName}/${repoName}/pulls/${pullId}`
|
||||
return await request(url, { accessToken })
|
||||
}
|
||||
|
||||
|
|
@ -115,7 +115,7 @@ export async function requestPullTreeData(
|
|||
accessToken?: string,
|
||||
) {
|
||||
const search = new URLSearchParams({ page: page.toString(), per_page: `${pageSize}` })
|
||||
const url = `https://${API_ENDPOINT}/repos/${userName}/${repoName}/pulls/${pullId}/files?${search}`
|
||||
const url = `${API_ENDPOINT}/repos/${userName}/${repoName}/pulls/${pullId}/files?${search}`
|
||||
return await request(url, { accessToken }, responseBodyResolvers.asIs)
|
||||
}
|
||||
|
||||
|
|
@ -136,7 +136,7 @@ export async function getPullComments(
|
|||
pullId: string,
|
||||
accessToken?: string,
|
||||
): Promise<GitHubAPI.PullComments> {
|
||||
const url = `https://${API_ENDPOINT}/repos/${userName}/${repoName}/pulls/${pullId}/comments`
|
||||
const url = `${API_ENDPOINT}/repos/${userName}/${repoName}/pulls/${pullId}/comments`
|
||||
return await request(url, { accessToken })
|
||||
}
|
||||
|
||||
|
|
@ -150,7 +150,7 @@ export async function getPullPageDocuments(
|
|||
return continuousLoadPages(
|
||||
document ||
|
||||
(await getDOM(
|
||||
`https://${window.location.host}/${userName}/${repoName}/pull/${pullId}/files?_pjax=%23js-repo-pjax-container`,
|
||||
`${window.location.origin}/${userName}/${repoName}/pull/${pullId}/files?_pjax=%23js-repo-pjax-container`,
|
||||
)),
|
||||
)
|
||||
}
|
||||
|
|
@ -169,14 +169,14 @@ export async function getBlobData(
|
|||
sha: string,
|
||||
accessToken?: string,
|
||||
): Promise<GitHubAPI.BlobData> {
|
||||
const url = `https://${API_ENDPOINT}/repos/${userName}/${repoName}/git/blobs/${sha}`
|
||||
const url = `${API_ENDPOINT}/repos/${userName}/${repoName}/git/blobs/${sha}`
|
||||
return await request(url, { accessToken })
|
||||
}
|
||||
|
||||
export async function OAuth(code: string): Promise<string | null> {
|
||||
try {
|
||||
const endpoint = `https://gitako.enix.one/oauth/github?`
|
||||
const res = await fetch(endpoint + new URLSearchParams({ code }).toString(), {
|
||||
const endpoint = `https://${gitakoServiceHost}/oauth/github?${new URLSearchParams({ code })}`
|
||||
const res = await fetch(endpoint, {
|
||||
method: 'post',
|
||||
})
|
||||
if (res.ok) {
|
||||
|
|
@ -201,7 +201,7 @@ export async function requestCommitTreeData(
|
|||
per_page: '100',
|
||||
page: `${page}`,
|
||||
})
|
||||
const url = `https://${API_ENDPOINT}/repos/${userName}/${repoName}/commits/${sha}?` + search
|
||||
const url = `${API_ENDPOINT}/repos/${userName}/${repoName}/commits/${sha}?${search}`
|
||||
return await request(url, { accessToken }, responseBodyResolvers.asIs)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { formatHash } from 'utils/general'
|
||||
import * as API from './API'
|
||||
import { getPRDiffTotalStat, getPullRequestFilesCount, isInPullFilesPage } from './DOMHelper'
|
||||
import { processTree } from './index'
|
||||
|
|
@ -51,23 +50,27 @@ export async function getPullRequestTreeData(
|
|||
}
|
||||
}
|
||||
|
||||
const urlMainPart = `https://${window.location.host}/${userName}/${repoName}/pull/${pullId}/files${window.location.search}`
|
||||
const url = new URL(window.location.href)
|
||||
url.pathname = `/${userName}/${repoName}/pull/${pullId}/files`
|
||||
const commentsMap = getCommentsMap(commentData)
|
||||
const nodes: TreeNode[] = treeData.map(
|
||||
({ filename, sha, additions, deletions, changes, status }) => ({
|
||||
path: filename || '',
|
||||
type: 'blob',
|
||||
name: filename?.split('/').pop() || '',
|
||||
url: `${urlMainPart}${formatHash(map.get(filename))}`,
|
||||
sha: sha,
|
||||
comments: commentsMap.get(filename),
|
||||
diff: {
|
||||
status,
|
||||
additions,
|
||||
deletions,
|
||||
changes,
|
||||
},
|
||||
}),
|
||||
({ filename, sha, additions, deletions, changes, status }) => {
|
||||
url.hash = map.get(filename) || ''
|
||||
return {
|
||||
path: filename || '',
|
||||
type: 'blob',
|
||||
name: filename?.split('/').pop() || '',
|
||||
url: `${url}`,
|
||||
sha,
|
||||
comments: commentsMap.get(filename),
|
||||
diff: {
|
||||
status,
|
||||
additions,
|
||||
deletions,
|
||||
changes,
|
||||
},
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
const root = processTree(nodes)
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ function getUrlForRedirect(
|
|||
// Modern browsers have great support for handling unsafe URL,
|
||||
// It may be possible to sanitize path with
|
||||
// `path => path.includes('#') ? path.replace(/#/g, '%23') : '...'
|
||||
return `https://${window.location.host}/${userName}/${repoName}/${type}/${branchName}/${path
|
||||
return `${window.location.origin}/${userName}/${repoName}/${type}/${branchName}/${path
|
||||
.split('/')
|
||||
.map(encodeURIComponent)
|
||||
.join('/')}`
|
||||
|
|
@ -144,8 +144,8 @@ export const GitHub: Platform = {
|
|||
return (await API.getRepoMeta(userName, repoName, accessToken)).default_branch
|
||||
},
|
||||
resolveUrlFromMetaData({ userName, repoName, branchName }) {
|
||||
const repoUrl = `https://${window.location.host}/${userName}/${repoName}`
|
||||
const userUrl = `https://${window.location.host}/${userName}`
|
||||
const repoUrl = `${window.location.origin}/${userName}/${repoName}`
|
||||
const userUrl = `${window.location.origin}/${userName}`
|
||||
const pullId = URLHelper.isInPullPage()
|
||||
const commitId = URLHelper.isInCommitPage()
|
||||
const branchUrl = pullId
|
||||
|
|
@ -200,7 +200,7 @@ export const GitHub: Platform = {
|
|||
scope: 'repo',
|
||||
redirect_uri: window.location.href,
|
||||
})
|
||||
return `https://github.com/login/oauth/authorize?` + params.toString()
|
||||
return `https://github.com/login/oauth/authorize?${params}`
|
||||
},
|
||||
usePlatformHooks() {
|
||||
const { copyFileButton, copySnippetButton, codeFolding } = useConfigs().value
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { raiseError } from 'analytics'
|
||||
import { errors } from 'platforms'
|
||||
import { is } from 'utils/is'
|
||||
import { gitakoServiceHost } from 'utils/networkService'
|
||||
|
||||
function isEmptyProject(content: JSONValue) {
|
||||
return is.JSON.object(content) && content?.['message'] === 'Git Repository is empty.'
|
||||
|
|
@ -58,7 +59,7 @@ async function request(
|
|||
}
|
||||
}
|
||||
|
||||
export const API_ENDPOINT = `${window.location.protocol}//${window.location.host}/api/v1`
|
||||
export const API_ENDPOINT = `${window.location.origin}/api/v1`
|
||||
|
||||
export async function getRepoMeta(
|
||||
userName: string,
|
||||
|
|
@ -78,7 +79,7 @@ export async function getTreeData(
|
|||
): Promise<GiteaAPI.TreeData> {
|
||||
const search = new URLSearchParams()
|
||||
if (recursive) search.set('recursive', '1')
|
||||
const url = `${API_ENDPOINT}/repos/${userName}/${repoName}/git/trees/${branchName}?` + search
|
||||
const url = `${API_ENDPOINT}/repos/${userName}/${repoName}/git/trees/${branchName}?${search}`
|
||||
return await request(url, { accessToken })
|
||||
}
|
||||
|
||||
|
|
@ -93,8 +94,8 @@ export async function getBlobData(
|
|||
}
|
||||
|
||||
export async function OAuth(code: string): Promise<string | null> {
|
||||
const endpoint = `https://gitako.enix.one/oauth/gitea?`
|
||||
const res = await fetch(endpoint + new URLSearchParams({ code }).toString(), {
|
||||
const endpoint = `https://${gitakoServiceHost}/oauth/gitea?${new URLSearchParams({ code })}`
|
||||
const res = await fetch(endpoint, {
|
||||
method: 'post',
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -67,9 +67,7 @@ function getUrlForRedirect(
|
|||
// Modern browsers have great support for handling unsafe URL,
|
||||
// It may be possible to sanitize path with
|
||||
// `path => path.includes('#') ? path.replace(/#/g, '%23') : '...'
|
||||
return `${window.location.protocol}//${
|
||||
window.location.host
|
||||
}/${userName}/${repoName}/src/branch/${branchName}/${path
|
||||
return `${window.location.origin}/${userName}/${repoName}/src/branch/${branchName}/${path
|
||||
.split('/')
|
||||
.map(encodeURIComponent)
|
||||
.join('/')}`
|
||||
|
|
@ -108,8 +106,8 @@ export const Gitea: Platform = {
|
|||
return data.default_branch
|
||||
},
|
||||
resolveUrlFromMetaData({ userName, repoName, branchName }) {
|
||||
const repoUrl = `${window.location.protocol}//${window.location.host}/${userName}/${repoName}`
|
||||
const userUrl = `${window.location.protocol}//${window.location.host}/${userName}`
|
||||
const repoUrl = `${window.location.origin}/${userName}/${repoName}`
|
||||
const userUrl = `${window.location.origin}/${userName}`
|
||||
const branchUrl = `${repoUrl}/src/branch/${branchName}`
|
||||
return {
|
||||
repoUrl,
|
||||
|
|
@ -169,7 +167,7 @@ export const Gitea: Platform = {
|
|||
return API.OAuth(code)
|
||||
},
|
||||
getOAuthLink() {
|
||||
return `${window.location.protocol}//${window.location.host}/api/v1/user/applications/oauth2`
|
||||
return `${window.location.origin}/api/v1/user/applications/oauth2`
|
||||
},
|
||||
usePlatformHooks() {
|
||||
useProgressBar()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { raiseError } from 'analytics'
|
||||
import { errors } from 'platforms'
|
||||
import { is } from 'utils/is'
|
||||
import { gitakoServiceHost } from 'utils/networkService'
|
||||
|
||||
function isEmptyProject(content: JSONValue) {
|
||||
return is.JSON.object(content) && content?.['message'] === 'Git Repository is empty.'
|
||||
|
|
@ -90,8 +91,8 @@ export async function getBlobData(
|
|||
}
|
||||
|
||||
export async function OAuth(code: string): Promise<string | null> {
|
||||
const endpoint = 'https://gitako.enix.one/oauth/gitee?'
|
||||
const res = await fetch(endpoint + new URLSearchParams({ code }).toString(), {
|
||||
const endpoint = `https://${gitakoServiceHost}/oauth/gitee?${new URLSearchParams({ code })}`
|
||||
const res = await fetch(endpoint, {
|
||||
method: 'post',
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import * as React from 'react'
|
|||
import { resolveGitModules } from 'utils/gitSubmodule'
|
||||
import { useOnPJAXDone } from 'utils/hooks/usePJAX'
|
||||
import { useProgressBar } from 'utils/hooks/useProgressBar'
|
||||
import { gitakoServiceHost } from 'utils/networkService'
|
||||
import { sortFoldersToFront } from 'utils/treeParser'
|
||||
import * as API from './API'
|
||||
import * as DOMHelper from './DOMHelper'
|
||||
|
|
@ -68,7 +69,7 @@ function getUrlForRedirect(
|
|||
type = 'blob',
|
||||
path = '',
|
||||
) {
|
||||
return `https://gitee.com/${userName}/${repoName}/${type}/${branchName}/${path}`
|
||||
return `${window.location.origin}/${userName}/${repoName}/${type}/${branchName}/${path}`
|
||||
}
|
||||
|
||||
export const Gitee: Platform = {
|
||||
|
|
@ -105,8 +106,8 @@ export const Gitee: Platform = {
|
|||
return data.default_branch
|
||||
},
|
||||
resolveUrlFromMetaData({ userName, repoName, branchName }) {
|
||||
const repoUrl = `https://${window.location.host}/${userName}/${repoName}`
|
||||
const userUrl = `https://${window.location.host}/${userName}`
|
||||
const repoUrl = `${window.location.origin}/${userName}/${repoName}`
|
||||
const userUrl = `${window.location.origin}/${userName}`
|
||||
const branchUrl = `${repoUrl}/tree/${branchName}`
|
||||
return {
|
||||
repoUrl,
|
||||
|
|
@ -167,11 +168,11 @@ export const Gitee: Platform = {
|
|||
client_id: GITEE_OAUTH.clientId,
|
||||
scope: 'projects',
|
||||
response_type: 'code',
|
||||
redirect_uri:
|
||||
'https://gitako.enix.one/redirect/?' +
|
||||
new URLSearchParams({ redirect: window.location.href }).toString(),
|
||||
redirect_uri: `https://${gitakoServiceHost}/redirect/?${new URLSearchParams({
|
||||
redirect: window.location.href,
|
||||
})}`,
|
||||
})
|
||||
return `https://gitee.com/oauth/authorize?` + params.toString()
|
||||
return `https://gitee.com/oauth/authorize?${params}`
|
||||
},
|
||||
setOAuth(code) {
|
||||
return API.OAuth(code)
|
||||
|
|
|
|||
|
|
@ -202,11 +202,6 @@ export function resolveDiffGraphMeta(additions: number, deletions: number, chang
|
|||
return { g, r, w }
|
||||
}
|
||||
|
||||
export function formatHash(hash?: string) {
|
||||
if (hash) return '#' + hash
|
||||
return ''
|
||||
}
|
||||
|
||||
export function forOf<T, R>(target: T, callback: <K extends keyof T>(key: K, value: T[K]) => R) {
|
||||
for (const key of Object.keys(target)) {
|
||||
const $key = key as keyof typeof target
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ function transformModuleGitURL(node: TreeNode, URL: string) {
|
|||
const matched = URL.match(subModuleURLRegex.git)
|
||||
if (!matched) return
|
||||
const [, userName, repoName] = matched
|
||||
return appendCommitPath(`https://${window.location.host}/${userName}/${repoName}`, node)
|
||||
return appendCommitPath(`${window.location.origin}/${userName}/${repoName}`, node)
|
||||
}
|
||||
|
||||
function cutDotGit(URL: string) {
|
||||
|
|
|
|||
1
src/utils/networkService.ts
Normal file
1
src/utils/networkService.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export const gitakoServiceHost = 'gitako.enix.one'
|
||||
Loading…
Reference in a new issue