Skip to content

Commit 6f1d69f

Browse files
committed
install, configure, and initialize social-app-pyramid
1 parent c968e58 commit 6f1d69f

File tree

6 files changed

+170
-1
lines changed

6 files changed

+170
-1
lines changed

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ module = [
7171
"pyqrcode.*",
7272
"requests_aws4auth.*", # https://github.com/tedder/requests-aws4auth/issues/53
7373
"rfc3986.*", # https://github.com/python-hyper/rfc3986/issues/122
74+
"social_pyramid.models",
7475
"transaction.*",
7576
"ua_parser.*", # https://github.com/ua-parser/uap-python/issues/110
7677
"venusian.*",

requirements/main.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ rfc3986
6565
sentry-sdk
6666
setuptools
6767
pypi-attestations==0.0.25
68+
social-auth-app-pyramid
6869
sqlalchemy[asyncio]>=2.0,<3.0
6970
stdlib-list
7071
stripe

requirements/main.txt

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,7 @@ cryptography==44.0.2 \
517517
# pypi-attestations
518518
# rfc3161-client
519519
# sigstore
520+
# social-auth-core
520521
# webauthn
521522
cssselect==1.3.0 \
522523
--hash=sha256:56d1bf3e198080cc1667e137bc51de9cadfca259f03c2d4e09037b3e01e30f0d \
@@ -530,6 +531,12 @@ datadog==0.51.0 \
530531
--hash=sha256:3279534f831ae0b4ae2d8ce42ef038b4ab38e667d7ed6ff7437982d7a0cf5250 \
531532
--hash=sha256:a9764f091c96af4e0996d4400b168fc5fba380f911d6d672c9dcd4773e29ea3f
532533
# via -r requirements/main.in
534+
defusedxml==0.7.1 \
535+
--hash=sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69 \
536+
--hash=sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61
537+
# via
538+
# python3-openid
539+
# social-auth-core
533540
deprecated==1.2.18 \
534541
--hash=sha256:422b6f6d859da6f2ef57857761bfb392480502a64c3028ca9bbe86085d72115d \
535542
--hash=sha256:bd5011788200372a32418f888e326a09ff80d0214bd961147cfed01b5c018eec
@@ -1458,6 +1465,12 @@ nh3==0.2.21 \
14581465
# via
14591466
# -r requirements/main.in
14601467
# readme-renderer
1468+
oauthlib==3.2.2 \
1469+
--hash=sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca \
1470+
--hash=sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918
1471+
# via
1472+
# requests-oauthlib
1473+
# social-auth-core
14611474
openapi-core==0.19.5 \
14621475
--hash=sha256:421e753da56c391704454e66afe4803a290108590ac8fa6f4a4487f4ec11f2d3 \
14631476
--hash=sha256:ef7210e83a59394f46ce282639d8d26ad6fc8094aa904c9c16eb1bac8908911f
@@ -1790,6 +1803,7 @@ pyjwt[crypto]==2.10.1 \
17901803
# -r requirements/main.in
17911804
# pyjwt
17921805
# sigstore
1806+
# social-auth-core
17931807
pymacaroons==0.13.0 \
17941808
--hash=sha256:1e6bba42a5f66c245adf38a5a4006a99dcc06a0703786ea636098667d42903b8 \
17951809
--hash=sha256:3e14dff6a262fdbf1a15e769ce635a8aea72e6f8f91e408f9a97166c53b91907
@@ -1883,6 +1897,10 @@ python-slugify==8.0.4 \
18831897
--hash=sha256:276540b79961052b66b7d116620b36518847f52d5fd9e3a70164fc8c50faa6b8 \
18841898
--hash=sha256:59202371d1d05b54a9e7720c5e038f928f45daaffe41dd10822f3907b937c856
18851899
# via -r requirements/main.in
1900+
python3-openid==3.2.0 \
1901+
--hash=sha256:33fbf6928f401e0b790151ed2b5290b02545e8775f982485205a066f874aaeaf \
1902+
--hash=sha256:6626f771e0417486701e0b4daff762e7212e820ca5b29fcc0d05f6f8736dfa6b
1903+
# via social-auth-core
18861904
pytz==2025.2 \
18871905
--hash=sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3 \
18881906
--hash=sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00
@@ -1983,7 +2001,9 @@ requests==2.32.3 \
19832001
# pypi-attestations
19842002
# requests-aws4auth
19852003
# requests-file
2004+
# requests-oauthlib
19862005
# sigstore
2006+
# social-auth-core
19872007
# stripe
19882008
# tldextract
19892009
requests-aws4auth==1.3.1 \
@@ -1994,6 +2014,10 @@ requests-file==2.1.0 \
19942014
--hash=sha256:0f549a3f3b0699415ac04d167e9cb39bccfb730cb832b4d20be3d9867356e658 \
19952015
--hash=sha256:cf270de5a4c5874e84599fc5778303d496c10ae5e870bfa378818f35d21bda5c
19962016
# via tldextract
2017+
requests-oauthlib==2.0.0 \
2018+
--hash=sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36 \
2019+
--hash=sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9
2020+
# via social-auth-core
19972021
rfc3161-client==1.0.1 \
19982022
--hash=sha256:081211a1b602b6dff7feb314d39ca2229c8db4e8cf55eef0c35b460470f4b2bb \
19992023
--hash=sha256:0d3db059fe08d8b6b06aff89e133fcc352ffea1a1dafadb116dda9dae59d0689 \
@@ -2183,6 +2207,23 @@ six==1.17.0 \
21832207
# pymacaroons
21842208
# python-dateutil
21852209
# rfc3339-validator
2210+
# social-auth-app-pyramid
2211+
# social-auth-storage-sqlalchemy
2212+
social-auth-app-pyramid==2.0.0 \
2213+
--hash=sha256:1bf21f0ff51a338cd6ca944d49509d042903dbae76b51bd54ce6c44eea9906b4 \
2214+
--hash=sha256:6f3a0f35ad0d226c7d23bec1e17790e36a7758aed3946a79cd94e1f917a6dbe0
2215+
# via -r requirements/main.in
2216+
social-auth-core==4.6.0 \
2217+
--hash=sha256:6d940c458c529d3689f2ceca2d944911a4b02d76e82d154688d1d3f75f12d168 \
2218+
--hash=sha256:ecf9ae1e2e5bb52741cedcaede943fe89a8ada23f9aad018f350d4839a9d3a90
2219+
# via
2220+
# social-auth-app-pyramid
2221+
# social-auth-storage-sqlalchemy
2222+
social-auth-storage-sqlalchemy==1.1.0 \
2223+
--hash=sha256:0f408106bacf22794628e42d95e104f29044cf21e7b894c3913e76d2ec0eaa3b \
2224+
--hash=sha256:3598835f33719e76a846eac69f1f49820f4f2c8edc86cc6479d5099457ec6121 \
2225+
--hash=sha256:6ccfe0502e07086eccdb606875106d7e2a29b9804d3c7b31d0f53ba6a50e8e29
2226+
# via social-auth-app-pyramid
21862227
sqlalchemy[asyncio]==2.0.40 \
21872228
--hash=sha256:00a494ea6f42a44c326477b5bee4e0fc75f6a80c01570a32b57e89cf0fbef85a \
21882229
--hash=sha256:0bb933a650323e476a2e4fbef8997a10d0003d4da996aad3fd7873e962fdde4d \
@@ -2246,6 +2287,7 @@ sqlalchemy[asyncio]==2.0.40 \
22462287
# alembic
22472288
# alembic-postgresql-enum
22482289
# paginate-sqlalchemy
2290+
# social-auth-storage-sqlalchemy
22492291
# zope-sqlalchemy
22502292
stdlib-list==0.11.1 \
22512293
--hash=sha256:9029ea5e3dfde8cd4294cfd4d1797be56a67fc4693c606181730148c3fd1da29 \

tests/unit/test_config.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ def __init__(self):
288288
whitenoise_serve_static=pretend.call_recorder(lambda *a, **kw: None),
289289
whitenoise_add_files=pretend.call_recorder(lambda *a, **kw: None),
290290
whitenoise_add_manifest=pretend.call_recorder(lambda *a, **kw: None),
291-
scan=pretend.call_recorder(lambda categories, ignore: None),
291+
scan=pretend.call_recorder(lambda categories, ignore=False: None),
292292
commit=pretend.call_recorder(lambda: None),
293293
add_view_deriver=pretend.call_recorder(lambda *a, **kw: None),
294294
)
@@ -429,6 +429,7 @@ def __init__(self):
429429
pretend.call(".cache"),
430430
pretend.call(".email"),
431431
pretend.call(".accounts"),
432+
pretend.call("social_pyramid"),
432433
pretend.call(".macaroons"),
433434
pretend.call(".oidc"),
434435
pretend.call(".attestations"),
@@ -520,6 +521,7 @@ def __init__(self):
520521
pretend.call(
521522
categories=(
522523
"pyramid",
524+
"social_pyramid",
523525
"warehouse",
524526
),
525527
ignore=["warehouse.migrations.env", "warehouse.celery", "warehouse.wsgi"],

warehouse/config.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,11 @@
3232
from pyramid.httpexceptions import HTTPBadRequest
3333
from pyramid.tweens import EXCVIEW
3434
from pyramid_rpc.xmlrpc import XMLRPCRenderer
35+
from social_pyramid.models import init_social
3536

3637
from warehouse.authnz import Permissions
3738
from warehouse.constants import MAX_FILESIZE, MAX_PROJECT_SIZE, ONE_GIB, ONE_MIB
39+
from warehouse.db import ModelBase, Session, metadata
3840
from warehouse.utils.static import ManifestCacheBuster
3941
from warehouse.utils.wsgi import ProxyFixer, VhmRootRemover
4042

@@ -821,6 +823,14 @@ def configure(settings=None):
821823
# Register our authentication support.
822824
config.include(".accounts")
823825

826+
# https://python-social-auth.readthedocs.io/en/latest/configuration/settings.html
827+
config.include("social_pyramid")
828+
config.registry.settings["SOCIAL_AUTH_USER_MODEL"] = (
829+
"warehouse.accounts.models.User"
830+
)
831+
if "social_auth_usersocialauth" not in metadata.tables:
832+
init_social(config, ModelBase, Session)
833+
824834
# Register support for Macaroon based authentication
825835
config.include(".macaroons")
826836

@@ -951,6 +961,7 @@ def configure(settings=None):
951961
config.scan(
952962
categories=(
953963
"pyramid",
964+
"social_pyramid",
954965
"warehouse",
955966
),
956967
ignore=["warehouse.migrations.env", "warehouse.celery", "warehouse.wsgi"],
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License");
2+
# you may not use this file except in compliance with the License.
3+
# You may obtain a copy of the License at
4+
#
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS,
9+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
# See the License for the specific language governing permissions and
11+
# limitations under the License.
12+
"""
13+
social auth models
14+
15+
Revision ID: fcb2e13374bb
16+
Revises: c8384ca429fc
17+
Create Date: 2025-04-27 16:01:36.308879
18+
"""
19+
20+
import social_sqlalchemy
21+
import sqlalchemy as sa
22+
23+
from alembic import op
24+
25+
revision = "fcb2e13374bb"
26+
down_revision = "13c1c0ac92e9"
27+
28+
29+
def upgrade():
30+
op.create_table(
31+
"social_auth_association",
32+
sa.Column("id", sa.Integer(), nullable=False),
33+
sa.Column("server_url", sa.String(length=255), nullable=True),
34+
sa.Column("handle", sa.String(length=255), nullable=True),
35+
sa.Column("secret", sa.String(length=255), nullable=True),
36+
sa.Column("issued", sa.Integer(), nullable=True),
37+
sa.Column("lifetime", sa.Integer(), nullable=True),
38+
sa.Column("assoc_type", sa.String(length=64), nullable=True),
39+
sa.PrimaryKeyConstraint("id"),
40+
sa.UniqueConstraint("server_url", "handle"),
41+
)
42+
op.create_table(
43+
"social_auth_code",
44+
sa.Column("id", sa.Integer(), nullable=False),
45+
sa.Column("email", sa.String(length=200), nullable=True),
46+
sa.Column("code", sa.String(length=32), nullable=True),
47+
sa.PrimaryKeyConstraint("id"),
48+
sa.UniqueConstraint("code", "email"),
49+
)
50+
op.create_index(
51+
op.f("ix_social_auth_code_code"), "social_auth_code", ["code"], unique=False
52+
)
53+
op.create_table(
54+
"social_auth_nonce",
55+
sa.Column("id", sa.Integer(), nullable=False),
56+
sa.Column("server_url", sa.String(length=255), nullable=True),
57+
sa.Column("timestamp", sa.Integer(), nullable=True),
58+
sa.Column("salt", sa.String(length=40), nullable=True),
59+
sa.PrimaryKeyConstraint("id"),
60+
sa.UniqueConstraint("server_url", "timestamp", "salt"),
61+
)
62+
op.create_table(
63+
"social_auth_partial",
64+
sa.Column("id", sa.Integer(), nullable=False),
65+
sa.Column("token", sa.String(length=32), nullable=True),
66+
sa.Column("data", social_sqlalchemy.storage.JSONType(), nullable=True),
67+
sa.Column("next_step", sa.Integer(), nullable=True),
68+
sa.Column("backend", sa.String(length=32), nullable=True),
69+
sa.PrimaryKeyConstraint("id"),
70+
)
71+
op.create_index(
72+
op.f("ix_social_auth_partial_token"),
73+
"social_auth_partial",
74+
["token"],
75+
unique=False,
76+
)
77+
op.create_table(
78+
"social_auth_usersocialauth",
79+
sa.Column("uid", sa.String(length=255), nullable=False),
80+
sa.Column("user_id", sa.UUID(), nullable=False),
81+
sa.Column("id", sa.Integer(), nullable=False),
82+
sa.Column("provider", sa.String(length=32), nullable=True),
83+
sa.Column("extra_data", social_sqlalchemy.storage.JSONType(), nullable=True),
84+
sa.ForeignKeyConstraint(
85+
["user_id"],
86+
["users.id"],
87+
),
88+
sa.PrimaryKeyConstraint("id"),
89+
sa.UniqueConstraint("provider", "uid"),
90+
)
91+
op.create_index(
92+
op.f("ix_social_auth_usersocialauth_user_id"),
93+
"social_auth_usersocialauth",
94+
["user_id"],
95+
unique=False,
96+
)
97+
98+
99+
def downgrade():
100+
op.drop_index(
101+
op.f("ix_social_auth_usersocialauth_user_id"),
102+
table_name="social_auth_usersocialauth",
103+
)
104+
op.drop_table("social_auth_usersocialauth")
105+
op.drop_index(
106+
op.f("ix_social_auth_partial_token"), table_name="social_auth_partial"
107+
)
108+
op.drop_table("social_auth_partial")
109+
op.drop_table("social_auth_nonce")
110+
op.drop_index(op.f("ix_social_auth_code_code"), table_name="social_auth_code")
111+
op.drop_table("social_auth_code")
112+
op.drop_table("social_auth_association")

0 commit comments

Comments
 (0)