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

Patreon (Step 1) #1396

Merged
merged 4 commits into from
Dec 4, 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
13 changes: 13 additions & 0 deletions api/proto/user_service/user_service.proto
Original file line number Diff line number Diff line change
Expand Up @@ -284,3 +284,16 @@ service SocializeService {
rpc GetChatsForChannel(GetChatsRequest) returns (ipc.ChatMessages);
rpc GetModList(GetModListRequest) returns (GetModListResponse);
}

message Integration {
string uuid = 1;
string integration_name = 2;
}

message GetIntegrationsRequest {}

message IntegrationsResponse { repeated Integration integrations = 1; }

service IntegrationService {
rpc GetIntegrations(GetIntegrationsRequest) returns (IntegrationsResponse);
}
19 changes: 19 additions & 0 deletions bruno/patreon/Get Campaign.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
meta {
name: Get Campaign
type: http
seq: 3
}

get {
url: https://www.patreon.com/api/oauth2/v2/campaigns/1311241?fields[campaign]=created_at,creation_name,discord_server_id,image_small_url,image_url,is_charged_immediately,is_monthly,main_video_embed,main_video_url,one_liner,one_liner,patron_count,pay_per_name,pledge_url,published_at,summary,thanks_embed,thanks_msg,thanks_video_url
body: none
auth: inherit
}

params:query {
fields[campaign]: created_at,creation_name,discord_server_id,image_small_url,image_url,is_charged_immediately,is_monthly,main_video_embed,main_video_url,one_liner,one_liner,patron_count,pay_per_name,pledge_url,published_at,summary,thanks_embed,thanks_msg,thanks_video_url
}

headers {
Content-Type: application/json
}
23 changes: 23 additions & 0 deletions bruno/patreon/Get Identity.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
meta {
name: Get Identity
type: http
seq: 2
}

get {
url: https://www.patreon.com/api/oauth2/v2/identity?fields[user]=email,first_name,last_name&fields[campaign]=summary,is_monthly&fields[member]=full_name,is_follower,last_charge_date,last_charge_status,lifetime_support_cents,currently_entitled_amount_cents,patron_status&fields[tier]=amount_cents,created_at,description,discord_role_ids,edited_at,patron_count,published,published_at,requires_shipping,title,url&include=memberships
body: none
auth: inherit
}

params:query {
fields[user]: email,first_name,last_name
fields[campaign]: summary,is_monthly
fields[member]: full_name,is_follower,last_charge_date,last_charge_status,lifetime_support_cents,currently_entitled_amount_cents,patron_status
fields[tier]: amount_cents,created_at,description,discord_role_ids,edited_at,patron_count,published,published_at,requires_shipping,title,url
include: memberships
}

headers {
Content-Type: application/json
}
21 changes: 21 additions & 0 deletions bruno/patreon/Get Member.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
meta {
name: Get Member
type: http
seq: 4
}

get {
url: https://www.patreon.com/api/oauth2/v2/members/b2fddab5-1ba5-402c-b825-7b4d8189c56a?fields[address]=line_1,line_2,addressee,postal_code,city&fields[member]=full_name,is_follower,last_charge_date&include=address,user
body: none
auth: inherit
}

params:query {
fields[address]: line_1,line_2,addressee,postal_code,city
fields[member]: full_name,is_follower,last_charge_date
include: address,user
}

headers {
Content-Type: application/json
}
9 changes: 9 additions & 0 deletions bruno/patreon/bruno.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"version": "1",
"name": "patreon",
"type": "collection",
"ignore": [
"node_modules",
".git"
]
}
7 changes: 7 additions & 0 deletions bruno/patreon/collection.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
auth {
mode: bearer
}

auth:bearer {
token: {{PATREON_TOKEN}}
}
3 changes: 3 additions & 0 deletions bruno/patreon/environments/Cesar - Patreon.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
vars:secret [
PATREON_TOKEN
]
19 changes: 19 additions & 0 deletions bruno/woogles-api/AuthenticationService/ChangePassword.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
meta {
name: ChangePassword
type: http
seq: 2
}

post {
url: {{baseURL}}/api/user_service.AuthenticationService/ChangePassword
body: json
auth: none
}

headers {
Cookie: session=yTJ8D2zEKQkxmnyUAGe7dJ
}

body:json {
{"old_password": "cesar", "password": "{{goodpassword}}"}
}
19 changes: 19 additions & 0 deletions bruno/woogles-api/AuthenticationService/Login.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
meta {
name: Login
type: http
seq: 1
}

post {
url: {{baseURL}}/api/user_service.AuthenticationService/Login
body: json
auth: none
}

headers {
:
}

body:json {
{"username": "cesar", "password": "{{goodpassword}}"}
}
21 changes: 21 additions & 0 deletions bruno/woogles-api/Get User Details.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
meta {
name: Get User Details
type: http
seq: 1
}

post {
url: {{baseURL}}/api/config_service.ConfigService/GetUserDetails
body: json
auth: none
}

body:json {
{
"username": "rightbehindyou"
}
}

assert {
res.body.is_admin: eq true
}
19 changes: 19 additions & 0 deletions bruno/woogles-api/RegistrationService/Register.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
meta {
name: Register
type: http
seq: 1
}

post {
url: {{baseURL}}/api/user_service.RegistrationService/Register
body: json
auth: none
}

headers {
:
}

body:json {
{"username": "use-a-slur-here-for-testing", "password": "password", "email": "foo"}
}
26 changes: 26 additions & 0 deletions bruno/woogles-api/Set User Permissions.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
meta {
name: Set User Permissions
type: http
seq: 3
}

post {
url: {{baseURL}}/api/config_service.ConfigService/SetUserPermissions
body: json
auth: none
}

body:json {
{
"username": "penumbra",
"director": false,
"admin": false,
"mod": true,
"bot": false

}
}

assert {
res.body.is_admin: eq true
}
17 changes: 17 additions & 0 deletions bruno/woogles-api/UserService/GetChatsForChannel.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
meta {
name: GetChatsForChannel
type: http
seq: 1
}

post {
url: {{baseURL}}/api/user_service.SocializeService/GetChatsForChannel
body: json
auth: none
}

body:json {
{
"channel": "chat.game.q4JhmVVm"
}
}
9 changes: 9 additions & 0 deletions bruno/woogles-api/bruno.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"version": "1",
"name": "woogles-api",
"type": "collection",
"ignore": [
"node_modules",
".git"
]
}
8 changes: 8 additions & 0 deletions bruno/woogles-api/collection.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
headers {
X-Api-Key: {{APIKey}}
Content-Type: application/json
}

auth {
mode: none
}
6 changes: 6 additions & 0 deletions bruno/woogles-api/environments/local.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
vars {
baseURL: http://liwords.localhost
}
vars:secret [
goodpassword
]
6 changes: 6 additions & 0 deletions bruno/woogles-api/environments/prod.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
vars {
baseURL: https://woogles.io
}
vars:secret [
APIKey
]
12 changes: 12 additions & 0 deletions cmd/liwords-api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import (
"github.com/woogles-io/liwords/pkg/comments"
"github.com/woogles-io/liwords/pkg/config"
"github.com/woogles-io/liwords/pkg/gameplay"
"github.com/woogles-io/liwords/pkg/integrations"
"github.com/woogles-io/liwords/pkg/memento"
"github.com/woogles-io/liwords/pkg/mod"
"github.com/woogles-io/liwords/pkg/omgwords"
Expand Down Expand Up @@ -193,6 +194,8 @@ func main() {

mementoService := memento.NewMementoService(stores.UserStore, stores.GameStore,
stores.GameDocumentStore, cfg)
oauthIntegrationService := integrations.NewOAuthIntegrationService(stores.SessionStore, stores.Queries, cfg)
integrationService := integrations.NewIntegrationService(stores.Queries)
authenticationService := auth.NewAuthenticationService(stores.UserStore, stores.SessionStore, stores.ConfigStore,
cfg.SecretKey, cfg.MailgunKey, cfg.DiscordToken, cfg.ArgonConfig)
registrationService := registration.NewRegistrationService(stores.UserStore, cfg.ArgonConfig)
Expand Down Expand Up @@ -223,6 +226,12 @@ func main() {
"memento-api",
otelhttp.WithSpanNameFormatter(customHTTPSpanNameFormatter),
)))
router.Handle(integrations.OAuthIntegrationServicePrefix,
otelhttp.WithRouteTag(integrations.OAuthIntegrationServicePrefix, otelhttp.NewHandler(
middlewares.Then(oauthIntegrationService),
"oauth-integration-handlers",
otelhttp.WithSpanNameFormatter(customHTTPSpanNameFormatter),
)))

interceptors := connect.WithInterceptors(otcInterceptor)
// We want to emit default values for backwards compatibility.
Expand Down Expand Up @@ -275,6 +284,9 @@ func main() {
connectapi.Handle(
comments_serviceconnect.NewGameCommentServiceHandler(commentService, options),
)
connectapi.Handle(
user_serviceconnect.NewIntegrationServiceHandler(integrationService, options),
)

connectapichain := middlewares.Then(connectapi)

Expand Down
5 changes: 5 additions & 0 deletions db/migrations/20241130115623_integrations.down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
BEGIN;

DROP TABLE integrations;

COMMIT;
15 changes: 15 additions & 0 deletions db/migrations/20241130115623_integrations.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
BEGIN;

CREATE TABLE integrations (
id BIGSERIAL PRIMARY KEY,
uuid UUID DEFAULT gen_random_uuid () NOT NULL UNIQUE,
user_id BIGINT NOT NULL,
integration_name TEXT NOT NULL,
data JSONB NOT NULL DEFAULT '{}'::jsonb,
FOREIGN KEY (user_id) REFERENCES users (id),
UNIQUE(user_id, integration_name)
);

CREATE INDEX integrations_user_idx ON integrations USING btree(user_id);

COMMIT;
18 changes: 18 additions & 0 deletions db/queries/integrations.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
-- name: AddOrUpdateIntegration :one
INSERT INTO integrations(user_id, integration_name, data)
VALUES (
(SELECT id FROM users WHERE users.uuid = @user_uuid),
$1,
$2
)
ON CONFLICT (user_id, integration_name)
DO UPDATE SET data = EXCLUDED.data
RETURNING integrations.uuid;

-- name: GetIntegrations :many
SELECT uuid, integration_name FROM integrations
WHERE user_id = (SELECT id from users where users.uuid = @user_uuid);

-- name: GetIntegrationData :one
SELECT data FROM integrations
WHERE uuid = $1;
5 changes: 4 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ services:
PUZZLE_GENERATION_TASK_DEFINITION: ${PUZZLE_GENERATION_TASK_DEFINITION:-}
OTEL_RESOURCE_ATTRIBUTES: "service.name=liwords,service.version=0.1.0"
OTEL_EXPORTER_OTLP_ENDPOINT: http://jaeger:4318
PATREON_CLIENT_ID: UhLzukHPyjascp5vNI0_AP5z_ABiz_6-sqU_y8YALVxiiJSxBqRQWFXxAox5vuqE
PATREON_CLIENT_SECRET: ${PATREON_CLIENT_SECRET:-}
PATREON_REDIRECT_URI: http://localhost/integrations/patreon/callback
volumes:
- .:/opt/program:rw
- ./data/lexica/gaddag:/opt/program/data/lexica/gaddag
Expand All @@ -56,7 +59,7 @@ services:
labels:
- "traefik.http.middlewares.floc.headers.customresponseheaders.Permissions-Policy=interest-cohort=()"
- "traefik.http.routers.liwords.middlewares=floc"
- "traefik.http.routers.liwords.rule=PathPrefix(`/api/`, `/gameimg/`, `/debug/`)"
- "traefik.http.routers.liwords.rule=PathPrefix(`/api/`, `/gameimg/`, `/debug/`, `/integrations/`)"
- "traefik.http.routers.liwords.entrypoints=web"
- "traefik.http.services.liwords.loadbalancer.server.port=8001"
- traefik.enable=true
Expand Down
2 changes: 2 additions & 0 deletions liwords-ui/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
PUBLIC_PATREON_CLIENT_ID=UhLzukHPyjascp5vNI0_AP5z_ABiz_6-sqU_y8YALVxiiJSxBqRQWFXxAox5vuqE
PUBLIC_PATREON_REDIRECT_URL=http://localhost/integrations/patreon/callback
2 changes: 2 additions & 0 deletions liwords-ui/.env.production
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
PUBLIC_PATREON_CLIENT_ID=VRup-HOI7HQ7bzBqrN2J4S9y1GRWtZcAW1aot8vdjnGQJv1V9hwItPhhIv-X68Wk
PUBLIC_PATREON_REDIRECT_URL=https://woogles.io/integrations/patreon/callback
4 changes: 2 additions & 2 deletions liwords-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"scripts": {
"analyze": "source-map-explorer 'build/static/js/*.js'",
"start": "rsbuild dev",
"build": "tsc && rsbuild build",
"build": "tsc && rsbuild build --env-mode production",
"preview": "rsbuild preview",
"test": "vitest",
"lint": "eslint --ext .js,.jsx,.ts,.tsx src --color",
Expand Down Expand Up @@ -75,4 +75,4 @@
"typescript": "^5.6.2",
"vitest": "^2.1.1"
}
}
}
Loading
Loading