Skip to content

Commit

Permalink
feat: enable the beta access (#178)
Browse files Browse the repository at this point in the history
* feat: enable the beta access

* fix: webhooks for beta is not catched correctly

* chore: update dependencies
  • Loading branch information
42atomys authored Jul 16, 2022
1 parent 8d4defb commit b170dc3
Show file tree
Hide file tree
Showing 17 changed files with 294 additions and 222 deletions.
3 changes: 1 addition & 2 deletions deploy/app/webhooked/base/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -178,5 +178,4 @@ data:
envRef: RABBITMQ_DATABASE_URL
queueName: webhooks-deliveries
contentType: application/json
durable: true
exchange: delayed
durable: true
63 changes: 44 additions & 19 deletions internal/webhooks/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,18 +108,33 @@ func (p *processor) Serve(amqpUrl, channel string) error {
return nil
}

// metadataWebhooked is the structure of the webhook metadata sent by the
// webhooked project formatted following this schema:
type metadataWebhooked struct {
Metadata struct {
// For duoapi webhooks the strcut is the type of the object with additionnal
// fields
duoapi.WebhookMetadata
// SpecName represents the spec name on wehooked configuration.
// Internally usage only.
SpecName string `json:"specName"`
} `json:"metadata"`
//Payload
Payload map[string]interface{} `json:"payload"`
}

// handler is the main function that processes the webhooks. It parses the
// webhook metadata and calls the appropriate processor function.
// This function is called by the Serve function on each incoming message.
func (p *processor) handler(data []byte) error {
md := &duoapi.Webhook{}
md := &metadataWebhooked{}

if err := json.Unmarshal(data, &md); err != nil {
log.Error().Err(err).Msg("Failed to unmarshal webhook metadata")
}

if md == nil || md.Metadata == nil {
log.Error().Str("payload", string(data)).Msg("Webhook metadata is nil")
if md == nil || md.Metadata.SpecName == "" {
log.Error().Str("payload", string(data)).Msg("Webhook metadata is invalid")
return ErrInvalidWebhook
}
log.Debug().Msgf("Received a message(%s.%s): %+v", md.Metadata.Model, md.Metadata.Event, md.Payload)
Expand All @@ -130,21 +145,10 @@ func (p *processor) handler(data []byte) error {
return p.githubHandler(data)
}

var err error
switch md.Metadata.Model {
case "location":
err = md.Payload.ProcessWebhook(p.ctx, md.Metadata, &locationProcessor{processor: p})
case "user":
err = md.Payload.ProcessWebhook(p.ctx, md.Metadata, &userProcessor{processor: p})
}
if err != nil {
log.Error().Err(err).Str("model", md.Metadata.Model).Str("event", md.Metadata.Event).Msg("Failed to process webhook")
return err
}

return nil
return p.duoHandler(data)
}

// githubHandler is the processor for the github webhooks.
func (p *processor) githubHandler(data []byte) error {
webhookPayload := &GithubSponsorshipWebhook{}
if err := json.Unmarshal(data, &webhookPayload); err != nil {
Expand Down Expand Up @@ -177,8 +181,7 @@ func (p *processor) githubHandler(data []byte) error {

var flagsList = user.FlagsList
switch webhookPayload.Action {
case "created":
case "edited":
case "created", "edited":
if webhookPayload.Sponsorship.Tier.MonthlyPriceInDollars >= 5 {
flagsList = append(flagsList, typesgen.FlagBeta.String(), typesgen.FlagDiscord.String())
}
Expand All @@ -191,6 +194,28 @@ func (p *processor) githubHandler(data []byte) error {
)
}

_, err = p.db.User.UpdateOne(user).SetFlagsList(flagsList).Save(p.ctx)
_, err = p.db.User.UpdateOne(user).SetFlagsList(utils.Uniq(flagsList)).Save(p.ctx)
return err
}

// duoHandler is the processor for the duo webhooks.
func (p *processor) duoHandler(data []byte) error {
mdDuo := &duoapi.Webhook{}
if err := json.Unmarshal(data, &mdDuo); err != nil {
log.Error().Err(err).Msg("Failed to unmarshal webhook metadata")
}

var err error
switch mdDuo.Metadata.Model {
case "location":
err = mdDuo.Payload.ProcessWebhook(p.ctx, mdDuo.Metadata, &locationProcessor{processor: p})
case "user":
err = mdDuo.Payload.ProcessWebhook(p.ctx, mdDuo.Metadata, &userProcessor{processor: p})
}
if err != nil {
log.Error().Err(err).Str("model", mdDuo.Metadata.Model).Str("event", mdDuo.Metadata.Event).Msg("Failed to process webhook")
return err
}

return nil
}
3 changes: 0 additions & 3 deletions pkg/duoapi/webhooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,6 @@ 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
13 changes: 13 additions & 0 deletions pkg/utils/slice.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,16 @@ func Contains[T comparable](slice []T, item T) bool {
}
return false
}

// Uniq returns a new slice with unique items from the given slice
func Uniq[T comparable](slice []T) []T {
var unique []T
for _, element := range slice {
if Contains(unique, element) {
continue
}

unique = append(unique, element)
}
return unique
}
8 changes: 4 additions & 4 deletions web/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@
"@apollo/react-hooks": "^4.0.0",
"@grpc/grpc-js": "^1.6.7",
"@headlessui/react": "^1.6.4",
"@sentry/nextjs": "^7.4.1",
"@sentry/tracing": "^7.4.1",
"@sentry/nextjs": "^7.7.0",
"@sentry/tracing": "^7.7.0",
"axios": "^0.26.1",
"classnames": "^2.3.1",
"google-protobuf": "^3.20.1-rc.1",
Expand Down Expand Up @@ -70,8 +70,8 @@
"@types/google-protobuf": "^3.15.6",
"@types/node": "17.0.33",
"@types/react": "^18.0.5",
"@typescript-eslint/eslint-plugin": "^5.27.1",
"@typescript-eslint/parser": "^5.23.0",
"@typescript-eslint/eslint-plugin": "^5.30.6",
"@typescript-eslint/parser": "^5.30.6",
"autoprefixer": "^10.4.7",
"babel-jest": "^28.1.0",
"babel-loader": "^8.2.3",
Expand Down
1 change: 1 addition & 0 deletions web/ui/sentry.client.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ if (process.env.NODE_ENV && process.env.NODE_ENV !== 'development') {
integrations: [new BrowserTracing()],
// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: process.env.NODE_ENV === 'production' ? 0.2 : 0,
sampleRate: 1,
// ...
// Note: if you want to override the automatic release value, do not set a
// `release` value here - use the environment variable `SENTRY_RELEASE`, so
Expand Down
1 change: 1 addition & 0 deletions web/ui/sentry.server.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ if (process.env.NODE_ENV && process.env.NODE_ENV !== 'development') {
integrations: [new BrowserTracing()],
// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: process.env.NODE_ENV === 'production' ? 0.2 : 0,
sampleRate: 1,
// ...
// Note: if you want to override the automatic release value, do not set a
// `release` value here - use the environment variable `SENTRY_RELEASE`, so
Expand Down
5 changes: 5 additions & 0 deletions web/ui/src/components/Sidebar/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ export const Sidebar = ({
<MenuItem href="/clusters" icon="fa-sitemap" name="Clusters" />
<MenuItem href="/friends" icon="fa-user-group" name="Friends" />
<MenuItem href="/statistics" icon="fa-chart-line" name="Statistics" />
<MenuItem
href="https://discord.gg/5f864c6hyj"
icon="fab fa-discord"
name="Discord"
/>
</nav>
<div
className={`${
Expand Down
36 changes: 36 additions & 0 deletions web/ui/src/components/Soon/Soon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* Soon is a component that shows a soon animation for part not yet implemented
*/
export const Soon = () => {
return (
<div className="text-4xl flex flex-col justify-center items-center w-full h-full bg-grid-400">
<h1 className="flex font-extrabold justify-center items-center mb-2 z-10">
<i
className="fa-duotone fa-forklift fa-bounce fa-2x"
style={
{
'--fa-animation-duration': '1000ms',
'--fa-primary-color': '#6366f1',
'--fa-secondary-color': '#6366f1',
} as React.CSSProperties
}
></i>

<span className="ml-4 text-indigo-500/50">Under construction</span>
</h1>
<small className="text-sm text-slate-500/60 text-center">
This part is not developed yet. Will be available during the beta phase.{' '}
<br />
You can help us by contributing to the idea on Discord.
</small>
<a
href="https://discord.gg/5f864c6hyj"
target="_blank"
rel="noopener noreferrer"
className="my-10 py-4 px-6 rounded-lg text-white text-lg bg-black font-medium border-2 border-black hover:px-14 hover:bg-slate-900 hover:border-indigo-500 focus:px-14 focus:border-indigo-500 focus:bg-indigo-500 transition-all"
>
Talk about it on Discord
</a>
</div>
);
};
1 change: 1 addition & 0 deletions web/ui/src/components/Soon/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Soon, Soon as default } from './Soon';
6 changes: 3 additions & 3 deletions web/ui/src/containers/clusters/ClusterSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export const ClusterSidebar = ({
<a>
<MenuItem
active={campus == 'helsinki' && cluster == 'c1'}
name=""
name="Cluster 1"
text="C1"
/>
</a>
Expand All @@ -64,7 +64,7 @@ export const ClusterSidebar = ({
<a>
<MenuItem
active={campus == 'helsinki' && cluster == 'c2'}
name=""
name="Cluster 2"
text="C2"
/>
</a>
Expand All @@ -73,7 +73,7 @@ export const ClusterSidebar = ({
<a>
<MenuItem
active={campus == 'helsinki' && cluster == 'c3'}
name=""
name="Cluster 3"
text="C3"
/>
</a>
Expand Down
4 changes: 2 additions & 2 deletions web/ui/src/pages/_middleware.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const middleware: NextMiddleware = async (req) => {
if (
pathname.startsWith('/api') ||
pathname.startsWith('/assets') ||
pathname.startsWith('/discord')
pathname.startsWith('/beta')
) {
return NextResponse.next();
}
Expand Down Expand Up @@ -36,5 +36,5 @@ export const middleware: NextMiddleware = async (req) => {
return NextResponse.next();
}

return NextResponse.redirect(new URL('/discord', req.url));
return NextResponse.redirect(new URL('/beta', req.url));
};
Loading

0 comments on commit b170dc3

Please sign in to comment.