Skip to content
This repository has been archived by the owner on Oct 4, 2023. It is now read-only.

Commit

Permalink
Add block remote config (#124)
Browse files Browse the repository at this point in the history
  • Loading branch information
raymondjacobson committed Nov 19, 2020
1 parent 2d6dd35 commit f9ae347
Show file tree
Hide file tree
Showing 15 changed files with 108 additions and 33 deletions.
1 change: 1 addition & 0 deletions packages/web/.circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,7 @@ jobs:
command: |
mv build-production build
cp ./resources/apple-app-site-association build
cp ./robots.txt build
echo ${GA_ACCESS_TOKEN} | npx wrangler secret put GA_ACCESS_TOKEN --env production
npx wrangler publish --env production
Expand Down
5 changes: 4 additions & 1 deletion packages/web/src/containers/deleted-page/DeletedPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@ type DeletedPageContentProps = {
canonicalUrl: string
playable: Playable
user: User
deletedByArtist?: boolean
}

const DeletedPage = ({
title,
description,
canonicalUrl,
playable,
user
user,
deletedByArtist = true
}: DeletedPageContentProps) => {
const isMobile = useIsMobile()

Expand All @@ -34,6 +36,7 @@ const DeletedPage = ({
canonicalUrl={canonicalUrl}
playable={playable}
user={user}
deletedByArtist={deletedByArtist}
>
{content}
</DeletedPageProvider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type OwnProps = {
canonicalUrl: string
user: User
playable: Playable
deletedByArtist: boolean

children:
| React.ComponentType<DesktopDeletedPageProps>
Expand All @@ -39,6 +40,7 @@ const DeletedPageProvider = ({
description,
canonicalUrl,
user,
deletedByArtist = true,
playable,
children: Children,
currentQueueItem,
Expand Down Expand Up @@ -88,7 +90,8 @@ const DeletedPageProvider = ({
playable,
user,
goToArtistPage,
getLineupProps
getLineupProps,
deletedByArtist
}

return <Children {...childProps} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ import Playable from 'models/Playable'
import { NestedNonNullable } from 'utils/typeUtils'

const messages = {
trackDeleted: 'Track [Deleted By Artist]',
trackDeleted: 'Track [Deleted]',
trackDeletedByArtist: 'Track [Deleted By Artist]',
playlistDeleted: 'Playlist [Deleted by Artist]',
albumDeleted: 'Album [Deleted By Artist]',
checkOut: (name: string) => `Check out more by ${name}`,
Expand Down Expand Up @@ -59,6 +60,7 @@ export type DeletedPageProps = {
title: string
description: string
canonicalUrl: string
deletedByArtist: boolean

playable: Playable
user: User | null
Expand All @@ -79,6 +81,7 @@ const DeletedPage = g(
canonicalUrl,
playable,
user,
deletedByArtist = true,
getLineupProps,
goToArtistPage
}) => {
Expand All @@ -91,6 +94,8 @@ const DeletedPage = g(
? isAlbum
? messages.albumDeleted
: messages.playlistDeleted
: deletedByArtist
? messages.trackDeletedByArtist
: messages.trackDeleted

const renderTile = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import Playable from 'models/Playable'
import { NestedNonNullable } from 'utils/typeUtils'

const messages = {
trackDeleted: 'Track [Deleted By Artist]',
trackDeleted: 'Track [Deleted]',
trackDeletedByArtist: 'Track [Deleted By Artist]',
playlistDeleted: 'Playlist [Deleted by Artist]',
albumDeleted: 'Album [Deleted By Artist]',
checkOut: (name: string) => `Check out more by ${name}`,
Expand Down Expand Up @@ -56,6 +57,7 @@ export type DeletedPageProps = {
title: string
description: string
canonicalUrl: string
deletedByArtist: boolean

playable: Playable
user: User | null
Expand All @@ -75,6 +77,7 @@ const DeletedPage = g(
description,
canonicalUrl,
playable,
deletedByArtist = true,
user,
getLineupProps,
goToArtistPage
Expand All @@ -88,6 +91,8 @@ const DeletedPage = g(
? isAlbum
? messages.albumDeleted
: messages.playlistDeleted
: deletedByArtist
? messages.trackDeletedByArtist
: messages.trackDeleted

const renderTile = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@ class TrackPageProvider extends Component<
canonicalUrl={canonicalUrl}
playable={{ metadata: track, type: PlayableType.TRACK }}
user={user}
deletedByArtist={!track._blocked}
/>
)
}
Expand Down
2 changes: 2 additions & 0 deletions packages/web/src/models/Track.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ export type ComputedTrackProperties = {
_remix_parents?: Array<{ track_id: ID }>
// Present iff the track has been cosigned
_co_sign?: Nullable<Remix>

_blocked?: boolean
}

export type Track = TrackMetadata & ComputedTrackProperties
Expand Down
33 changes: 15 additions & 18 deletions packages/web/src/services/AudiusBackend.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
import * as DiscoveryAPI from '@audius/libs/src/services/discoveryProvider/requests'
import * as IdentityAPI from '@audius/libs/src/services/identity/requests'
import { Timer } from 'utils/performance'
import { waitForRemoteConfig } from './remote-config/Provider'

export const IDENTITY_SERVICE = process.env.REACT_APP_IDENTITY_SERVICE
export const USER_NODE = process.env.REACT_APP_USER_NODE
Expand Down Expand Up @@ -56,6 +57,18 @@ export const AuthHeaders = Object.freeze({
Signature: 'Encoded-Data-Signature'
})

export const waitForWeb3 = async () => {
if (!window.web3Loaded) {
await new Promise(resolve => {
const onLoad = () => {
window.removeEventListener('WEB3_LOADED', onLoad)
resolve()
}
window.addEventListener('WEB3_LOADED', onLoad)
})
}
}

let AudiusLibs = null
let Utils = null
let SanityChecks = null
Expand Down Expand Up @@ -303,25 +316,9 @@ class AudiusBackend {

static async setup() {
// Wait for web3 to load if necessary
if (!window.web3Loaded) {
await new Promise(resolve => {
const onLoad = () => {
window.removeEventListener('WEB3_LOADED', onLoad)
resolve()
}
window.addEventListener('WEB3_LOADED', onLoad)
})
}
await waitForWeb3()
// Wait for optimizely to load if necessary
if (!window.optimizelyDatafile) {
await new Promise(resolve => {
const onLoad = () => {
window.removeEventListener('OPTIMIZELY_LOADED', onLoad)
resolve()
}
window.addEventListener('OPTIMIZELY_LOADED', onLoad)
})
}
await waitForRemoteConfig()

const { libs, libsUtils, libsSanityChecks } = await import(
'./audius-backend/AudiusLibsLazyLoader'
Expand Down
12 changes: 8 additions & 4 deletions packages/web/src/services/remote-config/Provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,7 @@ export function getFeatureEnabled(flag: FeatureFlags) {
}
}

// Internal

const init = async () => {
console.time('remote-config')
export const waitForRemoteConfig = async () => {
// Wait for optimizely to load if necessary (as it can be an async or defer tag)
// @ts-ignore: injected in index.html
if (!window.optimizelyDatafile) {
Expand All @@ -146,6 +143,13 @@ const init = async () => {
})
if (cb) window.removeEventListener('OPTIMIZELY_LOADED', cb)
}
}

// Internal

const init = async () => {
console.time('remote-config')
await waitForRemoteConfig()

provider = optimizely.createInstance({
// @ts-ignore: injected in index.html
Expand Down
7 changes: 6 additions & 1 deletion packages/web/src/services/remote-config/RemoteConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,12 @@ export enum StringKeys {
/**
* Custom eth provider urls to use for talking to main-net contracts
*/
ETH_PROVIDER_URLS = 'ETH_PROVIDER_URLS'
ETH_PROVIDER_URLS = 'ETH_PROVIDER_URLS',

/**
* Blocks content
*/
CONTENT_BLOCK_LIST = 'CONTENT_BLOCK_LIST'
}

export type AllRemoteConfigKeys =
Expand Down
3 changes: 2 additions & 1 deletion packages/web/src/services/remote-config/defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ export const remoteConfigStringDefaults: {
[StringKeys.AUDIUS_LOGO_VARIANT]: null,
[StringKeys.AUDIUS_LOGO_VARIANT_CLICK_TARGET]: null,
[StringKeys.APP_WIDE_NOTICE_TEXT]: null,
[StringKeys.ETH_PROVIDER_URLS]: ETH_PROVIDER_URLS
[StringKeys.ETH_PROVIDER_URLS]: ETH_PROVIDER_URLS,
[StringKeys.CONTENT_BLOCK_LIST]: null
}
export const remoteConfigDoubleDefaults: {
[key in DoubleKeys]: number | null
Expand Down
44 changes: 44 additions & 0 deletions packages/web/src/store/cache/tracks/utils/blocklist.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { getRemoteVar, StringKeys } from 'services/remote-config'
import { TrackMetadata } from 'models/Track'
import { waitForRemoteConfig } from 'services/remote-config/Provider'
import { waitForWeb3 } from 'services/AudiusBackend'

declare global {
interface Window {
Web3: any
}
}

const IS_WEB_HOSTNAME =
window.location.hostname === process.env.REACT_APP_PUBLIC_HOSTNAME

let blockList: Set<string>

const setBlocked = async <T extends TrackMetadata>(track: T) => {
// Initialize the set if not present
if (!blockList) {
await waitForRemoteConfig()
blockList = new Set(
(getRemoteVar(StringKeys.CONTENT_BLOCK_LIST) || '').split(',')
)
}
if (IS_WEB_HOSTNAME) {
await waitForWeb3()
const shaId = window.Web3.utils.sha3(track.track_id.toString())
if (blockList.has(shaId)) {
return {
...track,
is_delete: true,
_blocked: true
}
}
}
// Most of the time this method is a no-op
return track
}

export const setTracksIsBlocked = async <T extends TrackMetadata>(
tracks: T[]
): Promise<T[]> => {
return await Promise.all(tracks.map(setBlocked))
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { put } from 'redux-saga/effects'
import { put, call } from 'redux-saga/effects'
import * as cacheActions from 'store/cache/actions'
import { reformat } from './reformat'
import { Kind } from 'store/types'
import { makeUid } from 'utils/uid'
import { addUsersFromTracks } from './helpers'
import Track, { TrackMetadata } from 'models/Track'
import { setTracksIsBlocked } from './blocklist'

/**
* Processes tracks, adding users and calling `reformat`, before
Expand All @@ -17,8 +18,10 @@ export function* processAndCacheTracks<T extends TrackMetadata>(
// Add users
yield addUsersFromTracks(tracks)

const checkedTracks: T[] = yield call(setTracksIsBlocked, tracks)

// Remove users, add images
const reformattedTracks = tracks.map(reformat)
const reformattedTracks = checkedTracks.map(reformat)

// insert tracks into cache
yield put(
Expand Down
4 changes: 3 additions & 1 deletion packages/web/src/store/cache/tracks/utils/retrieveTracks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
import { fetchAndProcessStems } from './fetchAndProcessStems'
import apiClient from 'services/audius-api-client/AudiusAPIClient'
import { getUserId } from 'store/account/selectors'
import { setTracksIsBlocked } from './blocklist'

type UnlistedTrackRequest = { id: ID; url_title: string; handle: string }
type RetrieveTracksArgs = {
Expand Down Expand Up @@ -150,7 +151,8 @@ export function* retrieveTracks({
deleteExistingEntry: false,
onBeforeAddToCache: function* <T extends TrackMetadata>(tracks: T[]) {
yield addUsersFromTracks(tracks)
return tracks.map(track => reformat(track))
const checkedTracks = yield call(setTracksIsBlocked, tracks)
return checkedTracks.map(reformat)
}
})

Expand Down
3 changes: 1 addition & 2 deletions packages/web/src/store/reachability/sagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ const REACHABILITY_SHORT_TIMEOUT = 5 * 1000 // 5s
const REACHABILITY_REQUEST_TIMEOUT = 15 * 1000 // 15s

// Check that a response from REACHABILITY_URL is valid
const isResponseValid = (response: Response) =>
response && response.ok && response.status === 204
const isResponseValid = (response: Response) => response && response.ok

function* ping() {
// If there's no reachability url available, consider ourselves reachable
Expand Down

0 comments on commit f9ae347

Please sign in to comment.