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 workflow CI and add a new workflow for release to PYPI #12

Merged
merged 5 commits into from
Sep 29, 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
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ on:

jobs:
code-quality:
name: Code Quality
runs-on: ubuntu-latest
strategy:
matrix:
Expand All @@ -24,6 +25,7 @@ jobs:
run: pdm run ruff check --diff

testing:
name: Testing
runs-on: ubuntu-latest
strategy:
matrix:
Expand Down
16 changes: 16 additions & 0 deletions .github/workflows/release_to_pypi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: Release

on:
release:
types: [published]

jobs:
pypi-publish:
name: upload release to PyPI
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pdm-project/setup-pdm@v4
- name: Publish package distributions to PyPI
run: |
pdm publish --password ${{ secrets.PYPI_API_TOKEN }}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,6 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

# custom
prompt.md
234 changes: 234 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,235 @@
# SimpleSocialAuthLib

SimpleSocialAuthLib is a Python library designed to simplify social authentication for various providers. It offers a straightforward interface for handling OAuth2 flows and retrieving user data from popular social platforms.

## Contents

- [Why use SimpleSocialAuthLib?](#why-use-simplesocialauthlib)
- [Installation](#installation)
- [Configuration](#configuration)
- [Usage](#usage)
- [Returned Data Structure and OAuth URLs](#returned-data-structure-and-oauth-urls)
- [Full Example](#full-example)
- [Contributing](#contributing)
- [License](#license)

## Why use SimpleSocialAuthLib?

- **Simplicity**: Offers a clean and intuitive API for social authentication.
- **Flexibility**: Supports multiple social providers with a consistent interface.
- **Type Safety**: Utilizes Python type hints for better code quality and IDE support.
- **Extensibility**: Easily add new social providers by extending the base classes.

## Supported Social Providers

- [x] Google
- [x] GitHub

## Installation

Install SimpleSocialAuthLib:

```bash
# using pip
pip install simplesocialauthlib

# using pdm
pdm add simplesocialauthlib

# using uv
uv add simplesocialauthlib
```

## Configuration

Before using SimpleSocialAuthLib, you need to set up your social provider credentials. Here's how to configure for Google and GitHub:

### Google

1. Go to the [Google Cloud Console](https://console.cloud.google.com/).
2. Create a new project or select an existing one.
3. Enable the Google+ API.
4. Create OAuth 2.0 credentials (client ID and client secret).
5. Set up the authorized redirect URIs.

### GitHub

1. Go to your [GitHub Developer Settings](https://github.com/settings/developers).
2. Click on "New OAuth App".
3. Fill in the application details, including the callback URL.
4. Once created, you'll get a client ID and can generate a client secret.

## Usage

Here's a basic example of how to use SimpleSocialAuthLib with Google authentication:

```python
from simplesocialauthlib.providers.google import GoogleSocialAuth

# Initialize the Google auth provider
google_auth = GoogleSocialAuth(
client_id="your_google_client_id",
client_secret="your_google_client_secret",
redirect_uri="your_redirect_uri"
)

# After receiving the code from Google's OAuth redirect
code = "received_authorization_code"

# Complete the sign-in process
user_data = google_auth.sign_in(code=code)

# Use the user data as needed
print(f"Welcome, {user_data['full_name']}!")
```

## Returned Data Structure and OAuth URLs

### Google

**OAuth URL**:
```
https://accounts.google.com/o/oauth2/v2/auth?redirect_uri={{ GOOGLE_REDIRECT_URI }}&prompt=consent&response_type=code&client_id={{ GOOGLE_CLIENT_ID }}&scope=openid%20email%20profile&access_type=offline
```

**User Data Structure**:
```python
class GoogleUserData(TypedDict):
first_name: str
last_name: str
full_name: str
email: str
email_verified: bool
picture: str | None
```

### GitHub

**OAuth URL**:
```
https://github.com/login/oauth/authorize/?client_id={{ GITHUB_CLIENT_ID }}
```

**User Data Structure**:
```python
class GithubUserData(TypedDict):
username: str
full_name: str
email: str
picture: str | None
bio: str | None
location: str | None
```

## Full Example

Here's a full example using Flask to implement social login with both Google and GitHub:

```python
# app.py

import os
import logging

from flask import Flask, request, redirect, flash, render_template
from dotenv import load_dotenv

from simplesocialauthlib.providers.google import GoogleSocialAuth
from simplesocialauthlib.providers.github import GithubSocialAuth

load_dotenv()
logging.basicConfig(level=logging.INFO)

app = Flask(__name__)
app.secret_key = os.environ["SECRET_KEY"]


@app.route("/login")
def login():
return render_template(
"login.html",
GOOGLE_CLIENT_ID=os.environ["GOOGLE_CLIENT_ID"],
GOOGLE_REDIRECT_URI=os.environ["GOOGLE_REDIRECT_URI"],
GITHUB_CLIENT_ID=os.environ["GITHUB_CLIENT_ID"],
)


@app.route("/login/google")
def sign_in_with_google():
code = request.args.get("code")
if not code:
return redirect("/login")

try:
google_auth = GoogleSocialAuth(
client_id=os.environ["GOOGLE_CLIENT_ID"],
client_secret=os.environ["GOOGLE_CLIENT_SECRET"],
redirect_uri=os.environ["GOOGLE_REDIRECT_URI"]
)
user_data = google_auth.sign_in(code=code)
# Process user_data (e.g., create/update user in your database)
flash("You are now signed in with Google.", category="success")
return redirect("/")
except Exception as e:
logging.error(e)
flash("Something went wrong. Please try again.", category="danger")
return redirect("/login")


@app.route("/login/github")
def sign_in_with_github():
code = request.args.get("code")
if not code:
return redirect("/login")

try:
github_auth = GithubSocialAuth(
client_id=os.environ["GITHUB_CLIENT_ID"],
client_secret=os.environ["GITHUB_CLIENT_SECRET"]
)
user_data = github_auth.sign_in(code=code)
# Process user_data (e.g., create/update user in your database)
flash("You are now signed in with Github.", category="success")
return redirect("/")
except Exception as e:
logging.error(e)
flash("Something went wrong. Please try again.", category="danger")
return redirect("/login")


if __name__ == "__main__":
app.run(debug=True)
```

```html
<!-- login.html -->

...

<div class="d-grid gap-3 mx-auto" style="max-width: 320px;">
<!-- Google -->
<a
href="https://accounts.google.com/o/oauth2/v2/auth?redirect_uri={{ GOOGLE_REDIRECT_URI }}&prompt=consent&response_type=code&client_id={{ GOOGLE_CLIENT_ID }}&scope=openid%20email%20profile&access_type=offline"
>
<span>Login with Google</span>
</a>

<!-- Github -->
<a
href="https://github.com/login/oauth/authorize/?client_id={{ GITHUB_CLIENT_ID }}"
>
<span>Login with Github</span>
</a>
</div>

...

```

## Contributing

Contributions to SimpleSocialAuthLib are welcome! Please feel free to submit a Pull Request.

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
18 changes: 10 additions & 8 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
[project]
name = "SimpleSocialAuthLib"
dynamic = ["version"]
description = "SimpleSocialAuthLib is a lightweight and easy-to-use Python library that simplifies OAuth2 authentication integration with social providers such as Google, GitHub, Facebook, Twitter, and more."
description = "SimpleSocialAuthLib is a Python library designed to simplify social authentication for various providers. It offers a straightforward interface for handling OAuth2 flows and retrieving user data from popular social platforms."
authors = [
{name = "Macktireh", email = "abdimack97@gmail.com"},
]
readme = "README.md"
license = {text = "MIT"}
classifiers = [
"License :: OSI Approved :: MIT License",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.12",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Intended Audience :: Developers",
"Typing :: Typed",
"Topic :: Software Development :: Libraries"
]
requires-python = ">=3.12"
Expand All @@ -22,13 +23,18 @@ dependencies = [
"requests-oauthlib>=2.0.0",
]

[project.urls]
Homepage = "https://github.com/Macktireh/SimpleSocialAuthLib"
Documentation = "https://github.com/Macktireh/SimpleSocialAuthLib#readme"
Repository = "https://github.com/Macktireh/SimpleSocialAuthLib"
Issues = "https://github.com/Macktireh/SimpleSocialAuthLib/issues"


[tool.pdm]
distribution = true

[tool.pdm.version]
source = "file"
path = "src/simplesocialauthlib/__init__.py"
source = "scm"

[tool.pdm.dev-dependencies]
lint = [
Expand All @@ -53,10 +59,6 @@ url = "https://mirror.sjtu.edu.cn/pypi/web/simple"
name = "sjtug"


[tool.mypy]
ignore_missing_imports = true


[tool.ruff]
line-length = 130
exclude = [
Expand Down
2 changes: 0 additions & 2 deletions requirements/lint.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
mypy
pre-commit
ruff
types-requests
1 change: 0 additions & 1 deletion src/simplesocialauthlib/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
__version__ = "0.1.0"
2 changes: 1 addition & 1 deletion src/simplesocialauthlib/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
class GoogleUserData(TypedDict):
first_name: Annotated[str, "Corresponds to 'given_name' in Google API"]
last_name: Annotated[str, "Corresponds to 'family_name' in Google API"]
full_name: Annotated[str | None, "Corresponds to 'name' in Google API"]
full_name: Annotated[str, "Corresponds to 'name' in Google API"]
email: Annotated[str, "Corresponds to 'email' in Google API"]
email_verified: Annotated[bool, "Corresponds to 'email_verified' in Google API"]
picture: Annotated[str | None, "Corresponds to 'picture' in Google API"]
Expand Down