-
Notifications
You must be signed in to change notification settings - Fork 2
package inspector frontend first draft #73
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
Ph4t3
wants to merge
1
commit into
main
Choose a base branch
from
package-inspector
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| import { Container } from '@/components/top-level-pages/container' | ||
| import { Shield } from 'lucide-react' | ||
|
|
||
| export function PackageInspectorHero() { | ||
| return ( | ||
| <div className="relative"> | ||
| <div className="absolute inset-14 bottom-10 rounded-xl bg-gradient-to-r from-gray-950 to-black ring-1 ring-inset ring-white/10" /> | ||
| <Container className="relative"> | ||
| <div className="px-0 pb-12 pt-16 text-center max-md:pl-2 sm:pt-20 md:px-12 md:pb-16 md:pt-24 2xl:px-0"> | ||
| <div className="mb-6 inline-flex items-center gap-2 rounded-full bg-white/10 px-4 py-2 text-sm text-white/80"> | ||
| <Shield className="h-4 w-4" /> | ||
| Powered by DevGuard | ||
| </div> | ||
| <h1 className="text-5xl font-semibold leading-tight tracking-tight text-white/90"> | ||
| Package Inspector | ||
| </h1> | ||
| <p className="mx-auto mt-6 max-w-2xl text-lg text-white/70"> | ||
| Analyze the security state of open-source packages. Get | ||
| insights on maintenance, vulnerabilities, and supply | ||
| chain risks. | ||
| </p> | ||
| </div> | ||
| </Container> | ||
| </div> | ||
| ) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| import { useState } from 'react' | ||
| import { Searchbar } from '@/components/ui/Searchbar' | ||
| import { SearchResultCard } from './SearchResultCard' | ||
| import { PackageInspectorHero } from './Hero' | ||
| import mockData from './mock-data.json' | ||
|
|
||
| export function PackageInspectorPage() { | ||
| const [searchQuery, setSearchQuery] = useState('') | ||
|
|
||
| const [isLoading, setIsLoading] = useState(false) | ||
|
|
||
| const [results, setResults] = useState<any[]>([]) | ||
|
|
||
| const [hasSearched, setHasSearched] = useState(false) | ||
|
|
||
| const handleSearch = async () => { | ||
| if (!searchQuery.trim()) return | ||
|
|
||
| setIsLoading(true) | ||
| setHasSearched(true) | ||
|
|
||
| // TODO: replace with real API call when backend is ready | ||
| // simulate delay to test search button working and return mock data | ||
| await new Promise((resolve) => setTimeout(resolve, 1000)) | ||
| setResults([mockData]) | ||
| setIsLoading(false) | ||
| } | ||
|
|
||
| return ( | ||
| <> | ||
| <PackageInspectorHero /> | ||
| <div className="pb-16"> | ||
| <Searchbar | ||
| value={searchQuery} | ||
| onChange={setSearchQuery} | ||
| onSubmit={handleSearch} | ||
| isLoading={isLoading} | ||
| placeholder={'Search by package name or PURL'} | ||
| /> | ||
|
|
||
| {hasSearched && ( | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the hasSearched state can be removed. You can just check if results is empty or not |
||
| <div className="mx-auto mt-8 max-w-2xl"> | ||
| {results.map((result) => ( | ||
| <SearchResultCard | ||
| key={result.purl} | ||
| name={result.name} | ||
| description={result.project?.description} | ||
| version={result.version} | ||
| purl={result.purl} | ||
| /> | ||
| ))} | ||
| </div> | ||
| )} | ||
| </div> | ||
| </> | ||
| ) | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| import React from 'react' | ||
| import Link from 'next/link' | ||
| import { Package } from 'lucide-react' | ||
|
|
||
| interface SearchResultCardProps { | ||
| name: string | ||
| description?: string | ||
| version: string | ||
| purl: string | ||
| } | ||
|
|
||
| export function SearchResultCard({ | ||
| name, | ||
| description, | ||
| version, | ||
| purl, | ||
| }: SearchResultCardProps) { | ||
| const encodedPurl = encodeURIComponent(purl) | ||
|
|
||
| return ( | ||
| <Link | ||
| href={`/package-inspector/${encodedPurl}`} | ||
| className="flex items-center gap-4 rounded-lg border border-gray-200 bg-white p-4 transition-colors hover:border-gray-300 hover:bg-gray-50 dark:border-gray-700 dark:bg-gray-800 dark:hover:border-gray-600 dark:hover:bg-gray-700" | ||
| > | ||
| <div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-gray-100 dark:bg-gray-700"> | ||
| <Package className="h-5 w-5 text-gray-600 dark:text-gray-300" /> | ||
| </div> | ||
| <div className="min-w-0 flex-1"> | ||
| <div className="flex items-center gap-2"> | ||
| <span className="font-medium text-gray-900 dark:text-white"> | ||
| {name} | ||
| </span> | ||
| <span className="text-sm text-gray-500">v{version}</span> | ||
| </div> | ||
| {description && ( | ||
| <p className="truncate text-sm text-gray-600 dark:text-gray-400"> | ||
| {description} | ||
| </p> | ||
| )} | ||
| </div> | ||
| </Link> | ||
| ) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| { | ||
| "purl": "pkg:npm/event-stream@3.3.6", | ||
| "ecosystem": "npm", | ||
| "name": "event-stream", | ||
| "version": "3.3.6", | ||
|
|
||
| "project": { | ||
| "projectKey": "github.com/dominictarr/event-stream", | ||
| "starsCount": 1400, | ||
| "forksCount": 220, | ||
| "openIssuesCount": 12, | ||
| "homepage": "https://github.com/dominictarr/event-stream", | ||
| "license": "MIT", | ||
| "description": "Toolkit to make creating and working with streams easy", | ||
|
|
||
| "scoreCard": { | ||
| "checks": [ | ||
| { | ||
| "name": "Maintained", | ||
| "score": 2, | ||
| "reason": "No commit activity in the last 12 months" | ||
| }, | ||
| { | ||
| "name": "Code-Review", | ||
| "score": 3, | ||
| "reason": "Most commits are directly pushed to main without review" | ||
| }, | ||
| { | ||
| "name": "Signed-Releases", | ||
| "score": 0, | ||
| "reason": "No signed tags or releases detected" | ||
| }, | ||
| { | ||
| "name": "Signed-Commits", | ||
| "score": 1, | ||
| "reason": "Only a small subset of commits are signed" | ||
| }, | ||
| { | ||
| "name": "Branch-Protection", | ||
| "score": 0, | ||
| "reason": "Main branch allows force-pushes and direct commits" | ||
| }, | ||
| { | ||
| "name": "CI-Tests", | ||
| "score": 4, | ||
| "reason": "Basic CI exists but coverage is minimal" | ||
| }, | ||
| { | ||
| "name": "Fuzzing", | ||
| "score": 0, | ||
| "reason": "No fuzzing configuration detected" | ||
| }, | ||
| { | ||
| "name": "Dependency-Update-Tool", | ||
| "score": 2, | ||
| "reason": "Dependabot is configured but updates are often ignored" | ||
| }, | ||
| { | ||
| "name": "Security-Policy", | ||
| "score": 0, | ||
| "reason": "SECURITY.md not found" | ||
| }, | ||
| { | ||
| "name": "Vulnerabilities", | ||
| "score": 3, | ||
| "reason": "Known historical vulnerabilities with no documented remediation" | ||
| }, | ||
| { | ||
| "name": "Packaging", | ||
| "score": 1, | ||
| "reason": "Package includes postinstall scripts without sandboxing" | ||
| }, | ||
| { | ||
| "name": "Binary-Artifacts", | ||
| "score": 0, | ||
| "reason": "Prebuilt binaries committed to the repository" | ||
| } | ||
| ], | ||
| "metadata": { | ||
| "tool": "openssf-scorecard", | ||
| "toolVersion": "5.0.0", | ||
| "generatedAt": "2024-09-30T11:22:00Z" | ||
| } | ||
| }, | ||
|
|
||
| "scoreCardScore": 2.8, | ||
| "updatedAt": "2024-11-01T14:00:00Z" | ||
| }, | ||
|
|
||
| "maliciousPackage": { | ||
| "id": "MAL-2024-000123", | ||
| "summary": "Malicious package targeting CI environments", | ||
| "details": "The package executes a post-install script that exfiltrates environment variables and SSH keys.", | ||
| "published": "2024-10-12T08:15:30Z", | ||
| "modified": "2024-11-01T14:42:10Z", | ||
| "affectedComponent": { | ||
| "id": "mac-001", | ||
| "versionRange": "<=3.3.6", | ||
| "firstObserved": "2024-10-10T09:00:00Z" | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| import { Button } from './button' | ||
| import { Search } from 'lucide-react' | ||
|
|
||
| interface SearchbarProps { | ||
| value: string | ||
| onChange: (value: string) => void | ||
| onSubmit: () => void | ||
| isLoading?: boolean | ||
| placeholder?: string | ||
| // TODO: make button name customizable | ||
| } | ||
|
|
||
| export function Searchbar({ | ||
| value, | ||
| onChange, | ||
| onSubmit, | ||
| isLoading = false, | ||
| placeholder, | ||
| }: SearchbarProps) { | ||
| const handleSubmit = (e: React.FormEvent) => { | ||
| e.preventDefault() | ||
| onSubmit() | ||
| } | ||
|
|
||
| return ( | ||
| <div className="relative left-1/2 right-1/2 -mx-[50vw] w-screen px-4"> | ||
| <div className="mx-auto max-w-2xl"> | ||
| <form onSubmit={handleSubmit}> | ||
| <div className="relative"> | ||
| <Search className="absolute left-4 top-1/2 h-5 w-5 -translate-y-1/2 text-gray-400" /> | ||
| <input | ||
| type="text" | ||
| value={value} | ||
| onChange={(e) => onChange(e.target.value)} | ||
| className="w-full rounded-xl border border-gray-300 bg-white py-4 pl-12 pr-32 text-gray-900 placeholder-gray-500 focus:border-primary focus:outline-none focus:ring-primary dark:border-gray-800 dark:bg-gray-950 dark:text-white dark:focus:border-primary" | ||
| placeholder={placeholder} | ||
| /> | ||
| <Button | ||
| type="submit" | ||
| className="absolute right-2 top-1/2 -translate-y-1/2" | ||
| disabled={isLoading} | ||
| > | ||
| {isLoading ? 'Searching...' : 'Inspect'} | ||
| </Button> | ||
| </div> | ||
| </form> | ||
| </div> | ||
| </div> | ||
| ) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,46 +1,22 @@ | ||
| export default { | ||
| index: { | ||
| theme: { | ||
| layout: 'raw', | ||
| }, | ||
| display: 'hidden', | ||
| }, | ||
| pricing: { | ||
| theme: { | ||
| layout: 'raw', | ||
| }, | ||
| display: 'hidden', | ||
| }, | ||
| 'terms-of-use': { | ||
| display: 'hidden', | ||
| }, | ||
| 'privacy-policy': { | ||
| display: 'hidden', | ||
| }, | ||
| index: { theme: { layout: 'raw' }, display: 'hidden' }, | ||
| pricing: { theme: { layout: 'raw' }, display: 'hidden' }, | ||
| 'package-inspector': { theme: { layout: 'raw' }, display: 'hidden' }, | ||
| 'terms-of-use': { display: 'hidden' }, | ||
| 'privacy-policy': { display: 'hidden' }, | ||
| introduction: { title: 'Introduction' }, | ||
| 'getting-started': { title: 'Getting Started' }, | ||
| 'how-to-guides': { title: 'How-to Guides' }, | ||
| tutorials: { title: 'Tutorials' }, | ||
| explanations: { title: 'Explanations' }, | ||
| reference: { title: 'Reference' }, | ||
| contributing: { title: 'Contributing' }, | ||
| other: { | ||
| title: 'Other', | ||
| }, | ||
| 'header-pricing': { | ||
| title: 'Pricing', | ||
| type: 'page', | ||
| href: '/pricing', | ||
| }, | ||
| other: { title: 'Other' }, | ||
| 'header-pricing': { title: 'Pricing', type: 'page', href: '/pricing' }, | ||
| 'header-docs': { | ||
| title: 'Documentation', | ||
| type: 'page', | ||
| href: '/introduction', | ||
| }, | ||
| '404': { | ||
| theme: { | ||
| layout: 'raw', | ||
| }, | ||
| display: 'hidden', | ||
| }, | ||
| '404': { theme: { layout: 'raw' }, display: 'hidden' }, | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| --- | ||
| title: Package Inspector | ||
| description: Analyze the security state of open-source packages. Get insights on maintenance, vulnerabilities, and supply chain risks. | ||
| --- | ||
| import { PackageInspectorPage } from '@/components/package-inspector/PackageInspectorPage' | ||
|
|
||
| <PackageInspectorPage /> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| //results page coming soon |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export default { theme: { layout: 'raw' }, display: 'hidden' } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a lot of dependent state variables. Maybe we can use reacts useReducer hook to simplify? This is pretty nitpicking