Skip to content

Commit

Permalink
Merge branch 'main' into blog/impact-metrics-smol-edits
Browse files Browse the repository at this point in the history
  • Loading branch information
ccerv1 authored Mar 19, 2024
2 parents 1d5a847 + ab05239 commit fca67fa
Show file tree
Hide file tree
Showing 10 changed files with 173 additions and 55 deletions.
4 changes: 3 additions & 1 deletion .github/scripts/load-public-vars.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ function cleanup {
}
trap cleanup EXIT

docker pull ghcr.io/opensource-observer/oso-public-vars:latest

# Download the public vars
docker container create --name public-vars ghcr.io/opensource-observer/oso-public-vars:latest /bin/sh

Expand All @@ -35,9 +37,9 @@ docker cp public-vars:/public/. "${temp_dir}"

docker rm public-vars

export $(cat "${temp_dir}/vars.env" | xargs)

set_if_not_exists() {
export $(cat "${temp_dir}/vars.env" | xargs)
var_name=$1
dest=$2
public_var_name="PUBLIC_${var_name}"
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/ci-default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ jobs:
NEXT_PUBLIC_FEEDBACK_FARM_ID \
GOOGLE_TEST_DUMMY_CREDENTIALS_JSON \
X_GITHUB_GRAPHQL_API \
GOOGLE_PROJECT_ID
GOOGLE_PROJECT_ID \
PUBLIC_VARS_TEST
- name: Setup pnpm
uses: pnpm/action-setup@v2
Expand Down
18 changes: 14 additions & 4 deletions .github/workflows/refresh-test-credentials.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,25 +53,26 @@ jobs:
shell: bash
run: |
cd ops/external-prs &&
gcloud iam service-accounts keys create dummy.json --iam-account=[email protected] &&
bash scripts/rotate-service-account.sh [email protected] dummy.json &&
pnpm tools refresh-gcp-credentials --secret=false ${{ github.repository }} testing dummy.json GOOGLE_TEST_DUMMY_CREDENTIALS_JSON
# These credentials are intended to be secret
- name: Refresh credentials for the bigquery-admin user on the external-prs-app environment
shell: bash
run: |
cd ops/external-prs &&
gcloud iam service-accounts keys create bigquery-admin.json --iam-account=[email protected] &&
bash scripts/rotate-service-account.sh [email protected] bigquery-admin.json &&
pnpm tools refresh-gcp-credentials ${{ github.repository }} external-prs-app bigquery-admin.json GOOGLE_BQ_ADMIN_CREDENTIALS_JSON
rebuild-docker-public-vars:
name: rebuild-docker-public-vars
environment: testing
runs-on: ubuntu-latest

permissions:
packages: write

env:
DOCKER_PLATFORM: "amd64"
# Frontend variables
NODE_ENV: ${{ vars.NODE_ENV }}
PLASMIC_PROJECT_ID: ${{ vars.PLASMIC_PROJECT_ID }}
Expand All @@ -86,12 +87,20 @@ jobs:
# Indexer variables
X_GITHUB_GRAPHQL_API: ${{ vars.X_GITHUB_GRAPHQL_API }}
GOOGLE_PROJECT_ID: "opensource-observer"
PUBLIC_VARS_TEST: "THISISATEST"
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
fetch-depth: 1

- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Write public vars
run: |
bash .github/scripts/save-public-vars.sh ${{ github.sha }} \
Expand All @@ -104,4 +113,5 @@ jobs:
NEXT_PUBLIC_FEEDBACK_FARM_ID \
GOOGLE_TEST_DUMMY_CREDENTIALS_JSON \
X_GITHUB_GRAPHQL_API \
GOOGLE_PROJECT_ID
GOOGLE_PROJECT_ID \
PUBLIC_VARS_TEST
31 changes: 23 additions & 8 deletions apps/frontend/app/api/auth/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,25 @@ import { supabasePrivileged } from "../../../lib/clients/supabase";
import { jwtDecode } from "jwt-decode";
//import { logger } from "../../../lib/logger";

// Next.js route control
export const runtime = "edge"; // 'nodejs' (default) | 'edge'
//export const dynamic = "force-dynamic";
export const revalidate = 0;

// HTTP headers
const CACHE_CONTROL = "max-age=3600"; // in seconds
const HASURA_USER_ID_KEY = "x-hasura-user-id";
const AUTH_PREFIX = "bearer";

// Supabase schema
const DATA_COLLECTIVE_TABLE = "data_collective";
const API_KEY_TABLE = "api_keys";
const USER_ID_COLUMN = "user_id";
const API_KEY_COLUMN = "api_key";
const DELETED_COLUMN = "deleted_at";
const ALL_COLUMNS = `${USER_ID_COLUMN},${API_KEY_COLUMN},${DELETED_COLUMN}`;

// Helper functions for creating responses suitable for Hasura
const makeAnonRole = () => ({
"x-hasura-role": "anonymous",
});
Expand All @@ -31,9 +39,9 @@ const makeDevRole = (userId: string) => ({
});

/**
* This will return an array of all artifacts
* This is currently fetched by Algolia to build the search index
* @param _request
* Authentication check for Hasura GraphQL API
* Hasura will check this webhook on inbound requests
* @param request
* @returns
*/
export async function GET(request: NextRequest) {
Expand All @@ -54,13 +62,20 @@ export async function GET(request: NextRequest) {

// Try JWT decoding
try {
const decoded = jwtDecode(token);
console.log("JWT token: ", decoded);
// @TODO replace this library with one that verifies.
// Other existing npm libraries seem to struggle in an edge runtime.
const decoded: any = jwtDecode(token);
//console.log("JWT token: ", decoded);
const userId = decoded.app_metadata?.[HASURA_USER_ID_KEY];
if (userId) {
console.log(`/api/auth: valid JWT token => user`);
return NextResponse.json(makeUserRole(userId));
}
} catch (e) {
console.warn("JWT decoding error: ", e);
}

// Get the user
// Get the user by API token
const { data: keyData, error: keyError } = await supabasePrivileged
.from(API_KEY_TABLE)
.select(ALL_COLUMNS)
Expand All @@ -71,15 +86,15 @@ export async function GET(request: NextRequest) {
return NextResponse.json(makeAnonRole());
}

// Filter out inactive/deleted keys
const activeKeys = keyData.filter((x) => !x.deleted_at);
if (activeKeys.length < 1) {
console.log(`/api/auth: API key not valid => anon`);
return NextResponse.json(makeAnonRole());
}

const userId = activeKeys[0].user_id;

// Check for data collective membership
const userId = activeKeys[0].user_id;
const { data: collectiveData, error: collectiveError } =
await supabasePrivileged
.from(DATA_COLLECTIVE_TABLE)
Expand Down
58 changes: 35 additions & 23 deletions apps/frontend/app/project/[...slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,32 +62,44 @@ export default async function ProjectPage(props: ProjectPageProps) {
notFound();
}
const project = projectArray[0];
const projectId = project.project_id;
//console.log("project", project);

const { event_types: eventTypes } = await cachedGetAllEventTypes();
const { code_metrics_by_project: codeMetrics } =
await cachedGetCodeMetricsByProjectIds({
project_ids: [project.project_id],
});
const { onchain_metrics_by_project: onchainMetrics } =
await cachedGetOnchainMetricsByProjectIds({
project_ids: [project.project_id],
});
const { artifacts_by_project: artifactIds } =
await cachedGetArtifactIdsByProjectIds({
project_ids: [project.project_id],
});
const { projects_by_collection: collectionIds } =
await cachedGetCollectionIdsByProjectIds({
project_ids: [project.project_id],
});
const { artifacts } = await cachedGetArtifactsByIds({
artifact_ids: artifactIds.map((x: any) => x.artifact_id),
});
const { collections } = await cachedGetCollectionsByIds({
collection_ids: collectionIds.map((x: any) => x.collection_id),
});
// Parallelize getting things related to the project
const p1 = await Promise.all([
cachedGetAllEventTypes(),
cachedGetCodeMetricsByProjectIds({
project_ids: [projectId],
}),
cachedGetOnchainMetricsByProjectIds({
project_ids: [projectId],
}),
cachedGetArtifactIdsByProjectIds({
project_ids: [projectId],
}),
cachedGetCollectionIdsByProjectIds({
project_ids: [projectId],
}),
]);
const { event_types: eventTypes } = p1[0];
const { code_metrics_by_project: codeMetrics } = p1[1];
const { onchain_metrics_by_project: onchainMetrics } = p1[2];
const { artifacts_by_project: artifactIds } = p1[3];
const { projects_by_collection: collectionIds } = p1[4];

// Parallelize getting artifacts and collections
const p2 = await Promise.all([
cachedGetArtifactsByIds({
artifact_ids: artifactIds.map((x: any) => x.artifact_id),
}),
cachedGetCollectionsByIds({
collection_ids: collectionIds.map((x: any) => x.collection_id),
}),
]);
const { artifacts } = p2[0];
const { collections } = p2[1];

// Get Plasmic component
const plasmicData = await cachedFetchComponent(PLASMIC_COMPONENT);
const compMeta = plasmicData.entryCompMetas[0];

Expand Down
30 changes: 26 additions & 4 deletions apps/frontend/components/dataprovider/apollo-wrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,41 @@
"use client";

import { ApolloLink, HttpLink } from "@apollo/client";
import { ApolloLink, HttpLink, useApolloClient } from "@apollo/client";
import {
ApolloNextAppProvider,
NextSSRInMemoryCache,
NextSSRApolloClient,
SSRMultipartLink,
} from "@apollo/experimental-nextjs-app-support/ssr";
import { DB_GRAPHQL_URL } from "../../lib/config";
import { userToken } from "../../lib/clients/supabase";

function makeClient() {
// Supabase credentials get populated later on
let initialized = false;
const useEnsureAuth = () => {
const client = useApolloClient();
if (!initialized && userToken) {
client.setLink(makeLink());
initialized = true;
}
};

function makeLink() {
//console.log(userToken);
const httpLink = new HttpLink({
uri: DB_GRAPHQL_URL,
headers: userToken
? {
Authorization: `Bearer ${userToken}`,
}
: {},
});
return httpLink;
}

return new NextSSRApolloClient({
function makeClient() {
const httpLink = makeLink();
const client = new NextSSRApolloClient({
cache: new NextSSRInMemoryCache(),
link:
typeof window === "undefined"
Expand All @@ -26,6 +47,7 @@ function makeClient() {
])
: httpLink,
});
return client;
}

function ApolloWrapper({ children }: React.PropsWithChildren) {
Expand All @@ -36,4 +58,4 @@ function ApolloWrapper({ children }: React.PropsWithChildren) {
);
}

export { ApolloWrapper };
export { ApolloWrapper, useEnsureAuth };
21 changes: 9 additions & 12 deletions apps/frontend/components/dataprovider/event-data-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
CommonDataProviderRegistration,
} from "./provider-view";
import type { CommonDataProviderProps } from "./provider-view";
import { useEnsureAuth } from "./apollo-wrapper";

// Types used in the Plasmic registration
type BucketWidth = "day" | "week" | "month";
Expand Down Expand Up @@ -336,6 +337,7 @@ const formatData = (
* @returns
*/
function ArtifactEventDataProvider(props: EventDataProviderProps) {
useEnsureAuth();
const bucketWidth = getBucketWidth(props);
const query =
bucketWidth === "month"
Expand Down Expand Up @@ -388,9 +390,7 @@ function ArtifactEventDataProvider(props: EventDataProviderProps) {
const formattedData = formatData(props, normalizedEventData, entityData, {
gapFill: bucketWidth === "day",
});
if (!eventLoading) {
console.log(props, rawEventData, eventError, formattedData);
}
!eventLoading && console.log(props, rawEventData, eventError, formattedData);
return (
<DataProviderView
{...props}
Expand All @@ -407,6 +407,7 @@ function ArtifactEventDataProvider(props: EventDataProviderProps) {
* @returns
*/
function ProjectEventDataProvider(props: EventDataProviderProps) {
useEnsureAuth();
const bucketWidth = getBucketWidth(props);
const query =
bucketWidth === "month"
Expand Down Expand Up @@ -454,9 +455,7 @@ function ProjectEventDataProvider(props: EventDataProviderProps) {
const formattedData = formatData(props, normalizedData, entityData, {
gapFill: bucketWidth === "day",
});
if (!eventLoading) {
console.log(props, rawEventData, eventError, formattedData);
}
!eventLoading && console.log(props, rawEventData, eventError, formattedData);
return (
<DataProviderView
{...props}
Expand All @@ -473,6 +472,7 @@ function ProjectEventDataProvider(props: EventDataProviderProps) {
* @returns
*/
function CollectionEventDataProvider(props: EventDataProviderProps) {
useEnsureAuth();
const bucketWidth = getBucketWidth(props);
const query =
bucketWidth === "month"
Expand Down Expand Up @@ -523,9 +523,7 @@ function CollectionEventDataProvider(props: EventDataProviderProps) {
const formattedData = formatData(props, normalizedData, entityData, {
gapFill: bucketWidth === "day",
});
if (!eventLoading) {
console.log(props, rawEventData, eventError, formattedData);
}
!eventLoading && console.log(props, rawEventData, eventError, formattedData);
return (
<DataProviderView
{...props}
Expand All @@ -542,6 +540,7 @@ function CollectionEventDataProvider(props: EventDataProviderProps) {
* @returns
*/
function ProjectUserDataProvider(props: EventDataProviderProps) {
useEnsureAuth();
const {
data: rawEventData,
error: eventError,
Expand Down Expand Up @@ -577,9 +576,7 @@ function ProjectUserDataProvider(props: EventDataProviderProps) {
name: ensure<string>(x.project_name, "project missing 'project_name'"),
}));
const formattedData = formatData(props, normalizedData, entityData);
if (!eventLoading) {
console.log(props, rawEventData, eventError, formattedData);
}
!eventLoading && console.log(props, rawEventData, eventError, formattedData);
return (
<DataProviderView
{...props}
Expand Down
Loading

0 comments on commit fca67fa

Please sign in to comment.