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

update tools integration feedback #2

Merged
merged 16 commits into from
Feb 16, 2025
Merged
Show file tree
Hide file tree
Changes from 11 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
10 changes: 3 additions & 7 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
# Permit.io Configuration
PERMIT_API_KEY=your_permit_api_key_here
PERMIT_API_KEY=
JWKS_URL=
PERMIT_PDP_URL=

# JWT Configuration (optional)
JWT_SECRET_KEY=your_jwt_secret_key_here

# Optional PDP (Policy Decision Point) URL
PERMIT_PDP_URL=https://cloudpdp.api.permit.io
23 changes: 23 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Publish to PyPI

on:
release:
types: [created]

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v3
with:
python-version: "3.13"
- name: Install Poetry
run: |
curl -sSL https://install.python-poetry.org | python3 -
- name: Build and publish
run: |
poetry config pypi-token.pypi ${{ secrets.PYPI_TOKEN }}
poetry build
poetry publish
22 changes: 22 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Tests

on:
pull_request:
branches: [main]

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v3
with:
python-version: "3.13"
- name: Install Poetry
run: |
curl -sSL https://install.python-poetry.org | python3 -
- name: Install dependencies
run: poetry install
- name: Run tests
run: poetry run pytest
13 changes: 9 additions & 4 deletions langchain_permit/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from importlib import metadata


from langchain_permit.retrievers import LangchainPermitRetriever
from langchain_permit.tools import LangchainPermitTool
from langchain_permit.retrievers import PermitSelfQueryRetriever, PermitEnsembleRetriever
from langchain_permit.tools import LangchainPermissionsCheckTool
from langchain_permit.tools import LangchainJWTValidationTool
from langchain.schema.cache import BaseCache

try:
# __version__ = metadata.version(__package__)
Expand All @@ -13,7 +15,10 @@
del metadata # optional, avoids polluting the results of dir(__package__)

__all__ = [
"LangchainPermitRetriever",
"LangchainPermitTool",
"PermitSelfQueryRetriever",
"PermitEnsembleRetriever",
"LangchainPermissionsCheckTool",
"LangchainJWTValidationTool",
"BaseCache",
"__version__",
]
Empty file.
27 changes: 27 additions & 0 deletions langchain_permit/examples/secure_customer_docs/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from dotenv import load_dotenv
import os

# Load environment variables
load_dotenv()

# Permit.io configurations
PERMIT_API_KEY = os.getenv("PERMIT_API_KEY")
PERMIT_PDP_URL = os.getenv("PERMIT_PDP_URL")

# JWT configurations
JWKS_URL = os.getenv("JWKS_URL")

# Ensure required environment variables are set
required_vars = {
"PERMIT_API_KEY": PERMIT_API_KEY,
"PERMIT_PDP_URL": PERMIT_PDP_URL,
"JWKS_URL": JWKS_URL
}

for var_name, var_value in required_vars.items():
if not var_value:
raise ValueError(f"{var_name} must be set in environment variables")

# Basic configuration for the demo
RESOURCE_TYPE = "document" # The type of resource we're protecting
DEFAULT_ACTION = "read" # Default action for document access
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

Getting Started Guide

This guide will help you get started with our product's basic features.
1. Create your account
2. Set up your first project
3. Invite team members
4. Create and assign tasks

For advanced features, please upgrade to our premium tier.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

Product Overview - Basic Documentation

Welcome to our product! This basic guide covers the essential features
available to all users. Our product helps you manage and organize your work efficiently.

Key Features:
- Task Management
- Basic Reporting
- Team Collaboration
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

Advanced Features Documentation

This premium documentation covers advanced features available to premium users.

Advanced Features:
- Custom Workflows
- Advanced Analytics
- Priority Support
- API Access
- Custom Integrations
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

API Documentation

Comprehensive API documentation for premium users.

- Authentication
- Endpoints
- Rate Limits
- Example Implementations
- Best Practices
175 changes: 175 additions & 0 deletions langchain_permit/examples/secure_customer_docs/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
from config import PERMIT_API_KEY, PERMIT_PDP_URL, JWKS_URL
from langchain_permit.tools import LangchainJWTValidationTool, LangchainPermissionsCheckTool
from permit import Permit, User
# from langchain.docstore.document import Document
# from langchain_community.vectorstores import Chroma
from langchain_openai.llms import OpenAI
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain_permit.retrievers import PermitSelfQueryRetriever,PermitEnsembleRetriever
PermitSelfQueryRetriever.model_rebuild()
import os
from langchain_community.document_loaders import DirectoryLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
import asyncio
from langchain_community.document_loaders import DirectoryLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
# from langchain_community.embeddings import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
# from langchain_community.chat_models import ChatOpenAI
from langchain.schema import Document


# Initialize embeddings and documents
llm = ChatOpenAI(temperature=0)
embeddings = OpenAIEmbeddings()

# Example documents - replace with your actual documents
sample_documents = [
Document(
page_content="Example document 1 content",
metadata={
"id": "doc1",
"resource_type": "document"
}
),
Document(
page_content="Example document 2 content",
metadata={
"id": "doc2",
"resource_type": "document"
}
)
]

# Create vector store
vectorstore = Chroma.from_documents(
documents=sample_documents,
embedding=embeddings
)

async def retrieve_documents(user_claims, query: str):
"""Retrieve documents using PermitSelfQueryRetriever."""
try:
# Create Permit User object from claims
# permit_user = User(
# key=user_claims['sub'],
# name=user_claims['name']
# )

user_dict = {
"key": user_claims['sub'],
"name": user_claims['name']
}

# Initialize retriever
retriever = PermitSelfQueryRetriever(
llm=llm,
vectorstore=vectorstore,
user=user_dict,
resource_type="document",
action="read",
api_key=PERMIT_API_KEY,
pdp_url=PERMIT_PDP_URL
)

# Get relevant documents
docs = retriever.get_relevant_documents(query)

print(f"Retrieved {len(docs)} permitted documents:")
for doc in docs:
print(f"- Document ID: {doc.metadata.get('id')}")
print(f" Content: {doc.page_content[:100]}...")

return docs

except Exception as e:
print(f"Error retrieving documents: {str(e)}")
return []

# Initialize JWT validation tool
jwt_validator = LangchainJWTValidationTool(
jwks_url=JWKS_URL
)

permit_client = Permit(
token=PERMIT_API_KEY,
pdp=PERMIT_PDP_URL
)

permissions_checker = LangchainPermissionsCheckTool(
name="permission_check",
description="Check user permissions for documents",
permit=permit_client,
)

llm = ChatOpenAI(
temperature=0,
model="gpt-3.5-turbo"
)

async def validate_jwt_token(token: str):
"""Test JWT token validation using our validator."""
try:
claims = await jwt_validator._arun(token)
print("Token validated successfully!")
print("Claims:", claims)
return claims
except Exception as e:
print("Token validation failed:", str(e))
return None

async def check_permissions(user_claims):
"""Test permission checking using validated claims."""
try:
print("permit client", permit_client)
# Create a Permit User object from JWT claims
user = {
"key": user_claims['sub'],
"name": user_claims['name']
}
print("User object created:", user)

# Test permission check
result = await permissions_checker._arun(
user=user,
action="read",
resource="document"
)
print("Permission check result:", result)
return result
except Exception as e:
print("Permission check failed:", str(e))
return None

if __name__ == "__main__":
test_token = os.getenv("TEST_TOKEN")
# asyncio.run(validate_jwt_token(test_token))
# async def main():
# claims = await validate_jwt_token(test_token)
# if claims:
# await check_permissions(claims)

# asyncio.run(main())
async def main():
# First validate JWT token
claims = await validate_jwt_token(test_token)
if claims:
# Check permissions
has_permission = await check_permissions(claims)
if not has_permission:
# Perform document retrieval
query = "Find me documents about example content"
docs = await retrieve_documents(claims, query)

# You can now use these documents for your RAG pipeline
if docs:
print("\nSuccessfully retrieved permitted documents!")
else:
print("\nNo permitted documents found.")
else:
print("\nUser does not have permission to access documents.")
else:
print("\nFailed to validate JWT token.")

asyncio.run(main())

Loading