Skip to content
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

📦 NEW: API Security Consultant bot based on OWASP 2023 guidelines #7

Merged
merged 10 commits into from
Sep 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/api-sec-consultant/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
NEXT_LB_PIPE_API_KEY=""
54 changes: 54 additions & 0 deletions examples/api-sec-consultant/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env
.env*.local
.copy.local.env
.copy.remote.env

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts

# Supabase
seed.sql
xseed.sql
xxseed.sql
-seed.sql
/supabase/seed.sql
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/

# No lock files.
package-lock.json
yarn.lock
dist
78 changes: 78 additions & 0 deletions examples/api-sec-consultant/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
![Web API Security Consultant Bot by ⌘ Langbase][cover]

![License: MIT][mit] [![Fork to ⌘ Langbase][fork]][pipe]

## Build Web API Security Consultant Bot (OWASP 2023) with Pipes — ⌘ Langbase

This chatbot is built by using an AI Pipe on Langbase, it works with 30+ LLMs (OpenAI, Gemini, Mistral, Llama, Gemma, etc), any Data (10M+ context with Memory sets), and any Framework (standard web API you can use with any software).

Check out the live demo [here][demo].

## Features

- 💬 [Web API Security Consultant Bot][demo] — Built with an [AI Pipe on ⌘ Langbase][pipe]
- ⚡️ Streaming — Real-time chat experience with streamed responses
- 🗣️ Q/A — Ask questions and get pre-defined answers with your preferred AI model and tone
- 🔋 Responsive and open source — Works on all devices and platforms

## Learn more

1. Check the [Web API Security Consultant Bot on ⌘ Langbase][pipe]
2. Read the [source code on GitHub][gh] for this example
3. Go through Documentaion: [Pipe Quick Start][qs]
4. Learn more about [Pipes & Memory features on ⌘ Langbase][docs]

## Get started

Let's get started with the project:

To get started with Langbase, you'll need to [create a free personal account on Langbase.com][signup] and verify your email address. _Done? Cool, cool!_

1. Fork the [Web API Security Consultant Bot][pipe] Pipe on ⌘ Langbase.
2. Go to the API tab to copy the Pipe's API key (to be used on server-side only).
3. Download the example project folder from [here][download] or clone the reppository.
4. `cd` into the project directory and open it in your code editor.
5. Duplicate the `.env.example` file in this project and rename it to `.env.local`.
6. Add the following environment variables:
```
# Replace `PIPE_API_KEY` with the copied API key.
NEXT_LB_PIPE_API_KEY="PIPE_API_KEY"
```
7. In your CLI issue the following:
```
# Install the dependencies using the following command:
npm install

# Run the project using the following command:
npm run dev
```

8. Your app template should now be running on [localhost:3000][local].

> NOTE:
> This is a Next.js project, so you can build and deploy it to any platform of your choice, like Vercel, Netlify, Cloudflare, etc.

---

## Authors

This project is created by [Langbase][lb] team members, with contributions from:

- Muhammad-Ali Danish - Software Engineer, [Langbase][lb]

**_Built by ⌘ [Langbase.com][lb] — Ship hyper-personalized AI assistants with memory!_**

[cover]:https://raw.githubusercontent.com/LangbaseInc/docs-images/main/examples/api-sec-consultant/api-sec-consultant.png
[demo]: https://api-sec-consultant.langbase.dev
[lb]: https://langbase.com
[pipe]: https://beta.langbase.com/examples/api-sec-consultant
[gh]: https://github.com/LangbaseInc/langbase-examples/tree/main/examples/api-sec-consultant
[download]:https://download-directory.github.io/?url=https://github.com/LangbaseInc/langbase-examples/tree/main/examples/api-sec-consultant
[signup]: https://langbase.fyi/io
[qs]:https://langbase.com/docs/pipe/quickstart
[docs]:https://langbase.com/docs
[xaa]:https://x.com/MrAhmadAwais
[xab]:https://x.com/AhmadBilalDev
[local]:http://localhost:3000
[mit]: https://img.shields.io/badge/license-MIT-blue.svg?style=for-the-badge&color=%23000000
[fork]: https://img.shields.io/badge/FORK%20ON-%E2%8C%98%20Langbase-000000.svg?style=for-the-badge&logo=%E2%8C%98%20Langbase&logoColor=000000
57 changes: 57 additions & 0 deletions examples/api-sec-consultant/app/api/chat/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { OpenAIStream, StreamingTextResponse } from 'ai'

export const runtime = 'edge'

/**
* Stream AI Chat Messages from Langbase
*
* @param req
* @returns
*/
export async function POST(req: Request) {
try {
if (!process.env.NEXT_LB_PIPE_API_KEY) {
throw new Error(
'Please set NEXT_LB_PIPE_API_KEY in your environment variables.'
)
}

const endpointUrl = 'https://api.langbase.com/beta/chat'

const headers = {
'Content-Type': 'application/json',
Authorization: `Bearer ${process.env.NEXT_LB_PIPE_API_KEY}`
}

// Get chat prompt messages and threadId from the client.
const body = await req.json()
const { messages, threadId } = body

const requestBody = {
messages,
...(threadId && { threadId }) // Only include threadId if it exists
}

// Send the request to Langbase API.
const response = await fetch(endpointUrl, {
method: 'POST',
headers,
body: JSON.stringify(requestBody)
})

if (!response.ok) {
const res = await response.json()
throw new Error(`Error ${res.error.status}: ${res.error.message}`)
}

// Handle Langbase response, which is a stream in OpenAI format.
const stream = OpenAIStream(response)
// Respond with a text stream.
return new StreamingTextResponse(stream, {
headers: response.headers
})
} catch (error: any) {
console.error('Uncaught API Error:', error)
return new Response(JSON.stringify(error), { status: 500 })
}
}
Binary file added examples/api-sec-consultant/app/favicon.ico
Binary file not shown.
99 changes: 99 additions & 0 deletions examples/api-sec-consultant/app/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

/* Zinc */
/* --background: 240 10% 3.9%; */
/* --muted: 240 3.7% 15.9%; */
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
--card: 0 0% 100%;
--card-foreground: 240 10% 3.9%;
--popover: 0 0% 100%;
--popover-foreground: 240 10% 3.9%;
--primary: 240 5.9% 10%;
--primary-foreground: 0 0% 98%;
--secondary: 240 4.8% 95.9%;
--secondary-foreground: 240 5.9% 10%;
--muted: 240 4.8% 95.9%;
--muted-foreground: 240 3.8% 46.1%;
--accent: 240 4.8% 95.9%;
--accent-foreground: 240 5.9% 10%;
/* --destructive: 0 84.2% 60.2%; */
--destructive: 2.74 92.59% 62.94%;
--destructive-foreground: 0 0% 98%;
--warning: 46.38 70.61% 48.04%;
--warning-foreground: 120 12.5% 3.14%;
--border: 240 5.9% 90%;
--input: 240 5.9% 90%;
--ring: 240 5.9% 10%;
--radius: 6px;
--danger: 2.74 92.59% 62.94%;
}

.dark {
/* --background: 120 12.5% 3.14%; */
--background: 240, 3%, 9%;
--foreground: 0 0% 98%;
--card: 240 10% 3.9%;
--card-foreground: 0 0% 98%;
--popover: 240 10% 3.9%;
--popover-foreground: 0 0% 98%;
--primary: 0 0% 98%;
--primary-foreground: 240 5.9% 10%;
--secondary: 240 3.7% 15.9%;
--secondary-foreground: 0 0% 98%;
/* --muted: 165 10% 7.84%; */
--muted: 240 3.45% 11.37%;
--muted-foreground: 240 5% 64.9%;
--accent: 240 3.7% 15.9%;
--accent-foreground: 0 0% 98%;
/* --destructive: 0 62.8% 30.6%; */
--destructive: 356.18 70.61% 48.04%;
--destructive-foreground: 0 0% 98%;
--warning: 46.38 70.61% 48.04%;
--warning-foreground: 120 12.5% 3.14%;
/* --border: 240 3.7% 15.9%; */
--border: 240 2% 14%;
--border-muted: 240 2% 14%;
--input: 240 3.7% 15.9%;
--ring: 240 4.9% 83.9%;
--danger: 356.18 70.61% 48.04%;
}
}

@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}

::selection {
color: hsl(var(--background));
background: hsl(var(--foreground));
}

.google {
display: inline-block;
width: 20px;
height: 20px;
position: relative;
background-size: contain;
background-repeat: no-repeat;
background-position: 50%;
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 48 48'%3E%3Cdefs%3E%3Cpath id='a' d='M44.5 20H24v8.5h11.8C34.7 33.9 30.1 37 24 37c-7.2 0-13-5.8-13-13s5.8-13 13-13c3.1 0 5.9 1.1 8.1 2.9l6.4-6.4C34.6 4.1 29.6 2 24 2 11.8 2 2 11.8 2 24s9.8 22 22 22c11 0 21-8 21-22 0-1.3-.2-2.7-.5-4z'/%3E%3C/defs%3E%3CclipPath id='b'%3E%3Cuse xlink:href='%23a' overflow='visible'/%3E%3C/clipPath%3E%3Cpath clip-path='url(%23b)' fill='%23FBBC05' d='M0 37V11l17 13z'/%3E%3Cpath clip-path='url(%23b)' fill='%23EA4335' d='M0 11l17 13 7-6.1L48 14V0H0z'/%3E%3Cpath clip-path='url(%23b)' fill='%2334A853' d='M0 37l30-23 7.9 1L48 0v48H0z'/%3E%3Cpath clip-path='url(%23b)' fill='%234285F4' d='M48 48L17 24l-4-3 35-10z'/%3E%3C/svg%3E");
}

@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
36 changes: 36 additions & 0 deletions examples/api-sec-consultant/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Header } from '@/components/header'
import cn from 'mxcn'
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import { Toaster } from 'sonner'
import './globals.css'

const inter = Inter({ subsets: ['latin'] })

export const metadata: Metadata = {
title: 'Web API Security Consultant Bot - Langbase',
description: 'Build an Web API Security Consultant Chatbot with ⌘ Langbase using any LLM model.',
keywords: ['Web API Security Consultant', 'Chatbot', 'Langbase']
}

export default function RootLayout({
children
}: Readonly<{
children: React.ReactNode
}>) {
return (
<html lang="en">
<body className={cn(inter.className, 'dark bg-background')}>
<div className="flex min-h-screen flex-col px-3 pr-0 pt-6">
<div className="rounded-l-[calc(var(--radius)+2px)] border border-r-0 pb-1 pl-1">
<Toaster />
<Header />
<main className="rounded-l-[calc(var(--radius)+2px)] bg-muted">
{children}
</main>
</div>
</div>
</body>
</html>
)
}
7 changes: 7 additions & 0 deletions examples/api-sec-consultant/app/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Chatbot } from '@/components/chatbot-page'

export const runtime = 'edge'

export default function ChatPage() {
return <Chatbot />
}
Loading