Authorization: await getAuthorizationToken()

in hasher-matcher-actioner/webapp/src/Api.tsx [61:386]


      Authorization: await getAuthorizationToken(),
    },
    queryStringParameters: params,
  });
}

type MatchSummaries = {match_summaries: MatchDetails[]};

export async function fetchAllMatches(): Promise<MatchSummaries> {
  return apiGet('matches/');
}

export async function fetchMatchesFromSignal(
  signalSource: string,
  signalId: string,
): Promise<MatchSummaries> {
  return apiGet('matches/', {
    signal_q: signalId,
    signal_source: signalSource,
  });
}

export async function fetchMatchesFromContent(
  contentId: string,
): Promise<MatchSummaries> {
  return apiGet('matches/', {content_q: contentId});
}

type TESignalDetails = {
  privacy_group_id: string;
  tags: string[];
  opinion: string;
  pending_opinion_change: string;
};

type BankedSignalDetails = {
  bank_member_id: string;
  bank_id: string;
};

export type MatchDetails = {
  content_id: string;
  content_hash: string;
  signal_id: string;
  signal_hash: string;
  signal_source: string;
  signal_type: string;
  updated_at: string;
  te_signal_details: TESignalDetails[];
  banked_signal_details: BankedSignalDetails[];
};

type Matches = {match_details: MatchDetails[]};

export async function fetchMatchDetails(contentId: string): Promise<Matches> {
  return apiGet('matches/match/', {content_id: contentId});
}

export type HashDetails = {
  content_hash: string;
  updated_at: string;
};

export async function fetchHashDetails(
  contentId: string,
): Promise<HashDetails> {
  return apiGet('content/hash/', {content_id: contentId});
}

export async function fetchPreviewURL(
  contentId: string,
): Promise<{preview_url: string}> {
  return apiGet('content/preview-url/', {content_id: contentId});
}

export type ContentActionHistoryRecord = {
  action_label: string;
  performed_at: string;
};

type ContentActionHistoryRecords = {
  action_history: Array<ContentActionHistoryRecord>;
};

export async function fetchContentActionHistory(
  contentId: string,
): Promise<ContentActionHistoryRecords> {
  return apiGet('content/action-history/', {content_id: contentId});
}

export type ContentDetails = {
  content_id: string;
  content_type: string;

  content_ref: string;
  content_ref_type: string;

  submission_times: Array<string>;

  created_at: string;
  updated_at: string;
  additional_fields: Array<string>;
};

export async function fetchContentDetails(
  contentId: string,
): Promise<ContentDetails> {
  return apiGet('content/', {
    content_id: contentId,
  });
}

type ContentPipelineProgress = {
  content_type: string;
  content_preview_url: string;
  submitted_at: string;
  hashed_at: string;
  matched_at: string;
  action_evaluated_at: string;
  action_performed_at: string;
};

export async function fetchContentPipelineProgress(
  contentId: string,
): Promise<ContentPipelineProgress> {
  return apiGet('content/pipeline-progress/', {
    content_id: contentId,
  });
}

export async function fetchDashboardCardSummary(
  path: string,
): Promise<Response> {
  return apiGet(`${path}`);
}

export type StatsCard = {
  time_span_count: number;
  time_span: string;
  graph_data: Array<[number, number]>;
  last_updated: string;
};

type StatsResponse = {
  card: StatsCard;
};

export async function fetchStats(
  statName: string,
  timeSpan: string,
): Promise<StatsResponse> {
  return apiGet('stats/', {stat_name: statName, time_span: timeSpan});
}

export async function requestSignalOpinionChange(
  signalId: string,
  signalSource: string,
  privacyGroupId: string,
  opinionChange: string,
): Promise<void> {
  apiPost(
    '/matches/request-signal-opinion-change/',
    {},
    {
      signal_id: signalId,
      signal_source: signalSource,
      privacy_group_id: privacyGroupId,
      opinion_change: opinionChange,
    },
  );
}

export async function submitContentViaURL(
  contentId: string,
  contentType: string,
  additionalFields: string[],
  contentURL: string,
  forceResubmit: boolean,
): Promise<Response> {
  return apiPost('submit/url/', {
    content_id: contentId,
    content_type: contentType,
    additional_fields: additionalFields,
    content_url: contentURL,
    force_resubmit: forceResubmit,
  });
}

export async function submitContentViaPutURLUpload(
  contentId: string,
  contentType: string,
  additionalFields: string[],
  content: File,
  forceResubmit: boolean,
): Promise<Response> {
  const submitResponse = await apiPost<{presigned_url: string}>(
    'submit/put-url/',
    {
      content_id: contentId,
      content_type: contentType,
      additional_fields: additionalFields,
      file_type: content.type,
      force_resubmit: forceResubmit,
    },
  );

  const requestOptions = {
    method: 'PUT',
    body: content,
  };

  // Content object was created. Now the content itself needs to be uploaded to s3
  // using the put url in the response.
  const result = await fetch(submitResponse.presigned_url, requestOptions);
  return result;
}

type DatasetSummariesResponse = {
  threat_exchange_datasets: Array<Dataset>;
};
export async function fetchAllDatasets(): Promise<DatasetSummariesResponse> {
  return apiGet('datasets/');
}

export async function syncAllDatasets(): Promise<{response: string}> {
  return apiPost('datasets/sync');
}

export async function deleteDataset(key: string): Promise<{response: string}> {
  return apiPost(`datasets/delete/${key}`);
}

export type PrivacyGroup = {
  privacyGroupId: string;
  localFetcherActive: boolean;
  localWriteBack: boolean;
  localMatcherActive: boolean;
  localPDQMatchThreshold?: string;
};

type Dataset = {
  privacy_group_id: string;
  privacy_group_name: string;
  description: string;
  fetcher_active: boolean;
  matcher_active: boolean;
  write_back: boolean;
  in_use: boolean;
  hash_count: number;
  match_count: number;
  pdq_match_threshold?: string;
};

export async function updateDataset(
  privacyGroupId: string,
  fetcherActive: boolean,
  writeBack: boolean,
  matcherActive: boolean,
  pdqMatchThreshold?: string,
): Promise<Dataset> {
  return apiPost('datasets/update', {
    privacy_group_id: privacyGroupId,
    fetcher_active: fetcherActive,
    write_back: writeBack,
    matcher_active: matcherActive,
    pdq_match_threshold: pdqMatchThreshold,
  });
}

export async function createDataset(
  privacyGroupId: string,
  privacyGroupName: string,
  description = '',
  fetcherActive = false,
  writeBack = false,
  matcherActive = true,
): Promise<{response: string}> {
  return apiPost('datasets/create', {
    privacy_group_id: privacyGroupId,
    privacy_group_name: privacyGroupName,
    description,
    fetcher_active: fetcherActive,
    write_back: writeBack,
    matcher_active: matcherActive,
  });
}

export async function fetchHashCount(): Promise<Response> {
  return apiGet('hash-counts');
}

/**
 * Update ThreatExchange token to a new value. Backend will check whether the
 * token has appropriate access and only then succeed.
 *
 * Invalid token will return Promise(False); while valid token when set will
 * return Promise(True);
 *
 * @param token The new Token for access to ThreatExchange.
 */
export async function updateThreatExchangeAPIToken(
  token: string,
): Promise<boolean> {
  return apiPost('datasets/update-threatexchange-token', {token})
    .then(() => true)
    .catch(() => false);
}

// This class should be kept in sync with python class ActionPerformer (hmalib.common.configs.actioner.ActionPerformer)
type BackendActionPerformer = {
  name: string;
  config_subtype: string;
  url: string;
  headers: string;
  extension_name: string;
  additional_kwargs: Record<string, string>;
};

type AllActions = {
  error_message: string;
  actions_response: Array<BackendActionPerformer>;
};

export async function fetchAllActions(): Promise<ActionPerformer[]> {
  return apiGet<AllActions>('actions/').then(response => {
    if (response && !response.error_message && response.actions_response) {