fix(github-graphql): use getMediaDisplayURL to load media with auth header (#2652)

This commit is contained in:
Erez Rokah 2019-09-05 01:56:06 +03:00 committed by Shawn Erquhart
parent a801636967
commit e674e43f9f
7 changed files with 42 additions and 16 deletions

View File

@ -102,14 +102,14 @@ export default class API {
return textPromise; return textPromise;
} }
request(path, options = {}) { request(path, options = {}, parseResponse = response => this.parseResponse(response)) {
const headers = this.requestHeaders(options.headers || {}); const headers = this.requestHeaders(options.headers || {});
const url = this.urlFor(path, options); const url = this.urlFor(path, options);
let responseStatus; let responseStatus;
return fetch(url, { ...options, headers }) return fetch(url, { ...options, headers })
.then(response => { .then(response => {
responseStatus = response.status; responseStatus = response.status;
return this.parseResponse(response); return parseResponse(response);
}) })
.catch(error => { .catch(error => {
throw new APIError(error.message, responseStatus, 'GitHub'); throw new APIError(error.message, responseStatus, 'GitHub');

View File

@ -170,7 +170,7 @@ export default class GraphQLAPI extends API {
} else if (!is_binary) { } else if (!is_binary) {
return text; return text;
} else { } else {
return super.retrieveBlob(sha); return super.retrieveBlob(sha, repoURL);
} }
} }
@ -194,12 +194,13 @@ export default class GraphQLAPI extends API {
}); });
if (data.repository.object) { if (data.repository.object) {
const files = data.repository.object.entries.map(e => ({ const files = data.repository.object.entries
...e, .filter(({ type }) => type === 'blob')
path: `${path}/${e.name}`, .map(e => ({
download_url: `https://raw.githubusercontent.com/${this.repo}/${this.branch}/${path}/${e.name}`, ...e,
size: e.blob && e.blob.size, path: `${path}/${e.name}`,
})); size: e.blob && e.blob.size,
}));
return files; return files;
} else { } else {
throw new APIError('Not Found', 404, 'GitHub'); throw new APIError('Not Found', 404, 'GitHub');
@ -589,15 +590,15 @@ export default class GraphQLAPI extends API {
let entries = null; let entries = null;
if (commitTree.data.repository.commit.tree) { if (commitTree.data.repository.commit.tree) {
entries = commitTree.data.repository.commit.tree.entries; ({ entries, sha } = commitTree.data.repository.commit.tree);
} }
if (tree.data.repository.tree.entries) { if (tree.data.repository.tree.entries) {
entries = tree.data.repository.tree.entries; ({ entries, sha } = tree.data.repository.tree);
} }
if (entries) { if (entries) {
return { tree: entries.map(e => ({ ...e, mode: TREE_ENTRY_TYPE_TO_MODE[e.type] })) }; return { sha, tree: entries.map(e => ({ ...e, mode: TREE_ENTRY_TYPE_TO_MODE[e.type] })) };
} }
return Promise.reject('Could not get tree'); return Promise.reject('Could not get tree');

View File

@ -67,6 +67,7 @@ export const fileEntry = gql`
fragment FileEntryParts on TreeEntry { fragment FileEntryParts on TreeEntry {
name name
sha: oid sha: oid
type
blob: object { blob: object {
... on Blob { ... on Blob {
size: byteSize size: byteSize

View File

@ -259,15 +259,34 @@ export default class GitHub {
getMedia() { getMedia() {
return this.api.listFiles(this.config.get('media_folder')).then(files => return this.api.listFiles(this.config.get('media_folder')).then(files =>
files.map(({ sha, name, size, download_url, path }) => { files.map(({ sha, name, size, download_url, path }) => {
const url = new URL(download_url); if (download_url) {
if (url.pathname.match(/.svg$/)) { const url = new URL(download_url);
url.search += (url.search.slice(1) === '' ? '?' : '&') + 'sanitize=true'; if (url.pathname.match(/.svg$/)) {
url.search += (url.search.slice(1) === '' ? '?' : '&') + 'sanitize=true';
}
// if 'displayURL' is a string it will be loaded as is
return { id: sha, name, size, displayURL: url.href, path };
} else {
// if 'displayURL' is not a string it will be loaded using getMediaDisplayURL
return { id: sha, name, size, displayURL: { sha }, path };
} }
return { id: sha, name, size, displayURL: url.href, path };
}), }),
); );
} }
async getMediaDisplayURL(displayURL) {
const { sha } = displayURL;
const blob = await this.api.request(
`${this.api.repoURL}/git/blobs/${sha}`,
{
headers: { Accept: 'application/vnd.github.VERSION.raw' },
},
response => response.blob(),
);
return URL.createObjectURL(blob);
}
persistEntry(entry, mediaFiles = [], options = {}) { persistEntry(entry, mediaFiles = [], options = {}) {
return this.api.persistFiles(entry, mediaFiles, options); return this.api.persistFiles(entry, mediaFiles, options);
} }

View File

@ -100,6 +100,8 @@ MediaLibraryCard.propTypes = {
margin: PropTypes.string.isRequired, margin: PropTypes.string.isRequired,
isPrivate: PropTypes.bool, isPrivate: PropTypes.bool,
type: PropTypes.string, type: PropTypes.string,
isViewableImage: PropTypes.bool.isRequired,
loadDisplayURL: PropTypes.func.isRequired,
}; };
export default MediaLibraryCard; export default MediaLibraryCard;

View File

@ -86,6 +86,7 @@ MediaLibraryCardGrid.propTypes = {
cardMargin: PropTypes.string.isRequired, cardMargin: PropTypes.string.isRequired,
loadDisplayURL: PropTypes.func.isRequired, loadDisplayURL: PropTypes.func.isRequired,
isPrivate: PropTypes.bool, isPrivate: PropTypes.bool,
displayURLs: PropTypes.instanceOf(Map).isRequired,
}; };
export default MediaLibraryCardGrid; export default MediaLibraryCardGrid;

View File

@ -1,6 +1,7 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { Map } from 'immutable';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
import { translate } from 'react-polyglot'; import { translate } from 'react-polyglot';
import { Modal } from 'UI'; import { Modal } from 'UI';
@ -219,6 +220,7 @@ MediaLibraryModal.propTypes = {
handleLoadMore: PropTypes.func.isRequired, handleLoadMore: PropTypes.func.isRequired,
loadDisplayURL: PropTypes.func.isRequired, loadDisplayURL: PropTypes.func.isRequired,
t: PropTypes.func.isRequired, t: PropTypes.func.isRequired,
displayURLs: PropTypes.instanceOf(Map).isRequired,
}; };
export default translate()(MediaLibraryModal); export default translate()(MediaLibraryModal);