Skip to content

Commit

Permalink
feat: enable the github webhook to prepare the beta
Browse files Browse the repository at this point in the history
  • Loading branch information
42atomys committed Jul 11, 2022
1 parent 6df059c commit e4f2404
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 1 deletion.
37 changes: 36 additions & 1 deletion deploy/app/webhooked/base/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ data:
template.tpl: |
{
"metadata": {
"specName": "{{ .Spec.Name }}",
"model": "{{ .Request.Header | getHeader "X-Model" }}",
"event": "{{ .Request.Header | getHeader "X-Event" }}",
"deliveryID": "{{ .Request.Header | getHeader "X-Delivery" | default "unknown" }}"
Expand Down Expand Up @@ -146,4 +147,38 @@ data:
envRef: RABBITMQ_DATABASE_URL
queueName: webhooks-deliveries
contentType: application/json
durable: true
durable: true
- name: github-sponsorships
entrypointUrl: /github/sponsors
security:
- generate_hmac_256:
id: signature
inputs:
- name: payload
value: '{{ .Inputs.payload }}'
- name: secret
valueFrom:
envRef: GITHUB_WEBHOOK_SECRET
- header:
id: headerSignature
inputs:
- name: headerName
value: X-Hub-Signature-256
- compare:
inputs:
- name: first
value: '{{ .Outputs.headerSignature.value }}'
- name: second
value: 'sha256={{ .Outputs.signature.value }}'
formatting:
templatePath: /config/template.tpl
storage:
- type: rabbitmq
specs:
databaseUrl:
valueFrom:
envRef: RABBITMQ_DATABASE_URL
queueName: webhooks-deliveries
contentType: application/json
durable: true
exchange: delayed
58 changes: 58 additions & 0 deletions internal/webhooks/github.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package webhooks

import "time"

type GithubSponsorshipWebhook struct {
// The action that was performed. This can be one of created, cancelled,
// edited, tier_changed, pending_cancellation, or pending_tier_change.
// Note: The created action is only triggered after payment is processed.
Action string `json:"action"`
Sponsorship GithubSponsorship `json:"sponsorship"`
// The user that triggered the event.
Sender struct {
Login string `json:"login"`
ID int `json:"id"`
} `json:"sender"`
// The pending_cancellation and pending_tier_change event types will
// include the date the cancellation or tier change will take effect.
EffectiveDate time.Time `json:"effective_date"`
// The tier_changed and pending_tier_change will include the original
// tier before the change or pending change. For more information,
// see the pending tier change payload.
Changes struct {
Tier struct {
From GithubSponsorTier `json:"from"`
} `json:"tier"`
// The edited event types include the details about the change when
// someone edits a sponsorship to change the privacy.
PrivacyLevel string `json:"privacy_level"`
} `json:"changes"`
}

type GithubSponsorship struct {
CreatedAt time.Time `json:"created_at"`
Sponsorable struct {
Login string `json:"login"`
ID int `json:"id"`
AvatarURL string `json:"avatar_url"`
Type string `json:"type"`
} `json:"sponsorable"`
Sponsor struct {
Login string `json:"login"`
ID int `json:"id"`
AvatarURL string `json:"avatar_url"`
Type string `json:"type"`
} `json:"sponsor"`
PrivacyLevel string `json:"privacy_level"`
Tier GithubSponsorTier `json:"tier"`
}

type GithubSponsorTier struct {
CreatedAt time.Time `json:"created_at"`
Description string `json:"description"`
MonthlyPriceInCents int `json:"monthly_price_in_cents"`
MonthlyPriceInDollars int `json:"monthly_price_in_dollars"`
Name string `json:"name"`
IsOneTime bool `json:"is_one_time"`
IsCustomAmount bool `json:"is_custom_amount"`
}
50 changes: 50 additions & 0 deletions internal/webhooks/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@ import (
"encoding/json"
"errors"
"os"
"strconv"

"github.com/getsentry/sentry-go"
"github.com/rs/zerolog/log"
"github.com/streadway/amqp"

typesgen "atomys.codes/stud42/internal/api/generated/types"
modelsutils "atomys.codes/stud42/internal/models"
"atomys.codes/stud42/internal/models/generated"
modelgen "atomys.codes/stud42/internal/models/generated"
"atomys.codes/stud42/internal/models/generated/account"
"atomys.codes/stud42/internal/models/generated/user"
"atomys.codes/stud42/pkg/duoapi"
)

Expand Down Expand Up @@ -118,6 +123,12 @@ func (p *processor) handler(data []byte) error {
}
log.Debug().Msgf("Received a message(%s.%s): %+v", md.Metadata.Model, md.Metadata.Event, md.Payload)

// TODO: implement the processor for github and other webhooks
// Why: Bet need to be open and github sponsorship is a requirement to open it
if md.Metadata.SpecName == "github-sponsorships" {
return p.githubHandler(data)
}

var err error
switch md.Metadata.Model {
case "location":
Expand All @@ -132,3 +143,42 @@ func (p *processor) handler(data []byte) error {

return nil
}

func (p *processor) githubHandler(data []byte) error {
webhookPayload := &GithubSponsorshipWebhook{}
if err := json.Unmarshal(data, &webhookPayload); err != nil {
log.Error().Err(err).Msg("Failed to unmarshal webhook payload")
return err
}

sentry.CaptureEvent(&sentry.Event{
Level: sentry.LevelInfo,
Message: "Received a message(github-sponsorships)",
Extra: map[string]interface{}{
"webhook": webhookPayload,
},
})

_, err := p.db.User.
Query().
Where(
user.HasAccountsWith(
account.Provider(typesgen.ProviderGithub.String()),
account.ProviderAccountID(strconv.Itoa(webhookPayload.Sender.ID)),
),
).
First(p.ctx)
if err != nil && !generated.IsNotFound(err) {
return err
} else if generated.IsNotFound(err) {
return nil
}

switch webhookPayload.Action {
case "created":
case "edited":
case "cancelled":
}

return nil
}
3 changes: 3 additions & 0 deletions pkg/duoapi/webhooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ type IWebhookPayload interface {
// This informations is sended originally by the 42 API on the Header of the
// webhook.
type WebhookMetadata struct {
// SpecName represents the spec name on wehooked configuration.
// Internally usage only.
SpecName string `json:"specName"`
// Event is the event that triggered the webhook. (Header: X-Event)
// Possible values are listed on the interface {Model}WebhookProcessor.
Event string `json:"event"`
Expand Down

0 comments on commit e4f2404

Please sign in to comment.