Skip to content
This repository was archived by the owner on May 30, 2024. It is now read-only.

Commit 06a1555

Browse files
author
Noah Lee
authored
Refactoring the event API (#415)
* Fix API for event * Fix to dispatch event with deployment or review * Replace the `subscribeEvent` method * Fix the permission logic for streaming
1 parent 563964c commit 06a1555

File tree

12 files changed

+180
-408
lines changed

12 files changed

+180
-408
lines changed

internal/server/api/v1/stream/events.go

Lines changed: 46 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,11 @@
22
// Use of this source code is governed by the Gitploy Non-Commercial License
33
// that can be found in the LICENSE file.
44

5-
// +build !oss
5+
//go:build !oss
66

77
package stream
88

99
import (
10-
"context"
11-
"fmt"
12-
"math/rand"
1310
"time"
1411

1512
"github.com/gin-contrib/sse"
@@ -19,7 +16,6 @@ import (
1916
gb "github.com/gitploy-io/gitploy/internal/server/global"
2017
"github.com/gitploy-io/gitploy/model/ent"
2118
"github.com/gitploy-io/gitploy/model/ent/event"
22-
"github.com/gitploy-io/gitploy/pkg/e"
2319
)
2420

2521
// GetEvents streams events of deployment, or review.
@@ -29,30 +25,56 @@ func (s *Stream) GetEvents(c *gin.Context) {
2925
v, _ := c.Get(gb.KeyUser)
3026
u, _ := v.(*ent.User)
3127

32-
debugID := randstr()
33-
34-
events := make(chan *ent.Event, 10)
28+
events := make(chan *sse.Event, 10)
3529

3630
// Subscribe events
3731
// it'll unsubscribe after the connection is closed.
3832
sub := func(e *ent.Event) {
39-
40-
// Deleted type is always propagated to all.
41-
if e.Type == event.TypeDeleted {
42-
events <- e
43-
return
44-
}
45-
46-
if ok, err := s.hasPermForEvent(ctx, u, e); err != nil {
47-
s.log.Error("It has failed to check the perm.", zap.Error(err))
48-
return
49-
} else if !ok {
50-
s.log.Debug("Skip the event. The user has not the perm.")
51-
return
33+
switch e.Kind {
34+
case event.KindDeployment:
35+
d, err := s.i.FindDeploymentByID(ctx, e.DeploymentID)
36+
if err != nil {
37+
s.log.Error("Failed to find the deployment.", zap.Error(err))
38+
return
39+
}
40+
41+
if _, err := s.i.FindPermOfRepo(ctx, d.Edges.Repo, u); err != nil {
42+
s.log.Debug("Skip the event. The permission is denied.")
43+
return
44+
}
45+
46+
s.log.Debug("Dispatch a deployment event.", zap.Int("id", d.ID))
47+
events <- &sse.Event{
48+
Event: "deployment",
49+
Data: d,
50+
}
51+
52+
case event.KindReview:
53+
r, err := s.i.FindReviewByID(ctx, e.ReviewID)
54+
if err != nil {
55+
s.log.Error("Failed to find the review.", zap.Error(err))
56+
return
57+
}
58+
59+
d, err := s.i.FindDeploymentByID(ctx, r.DeploymentID)
60+
if err != nil {
61+
s.log.Error("Failed to find the deployment.", zap.Error(err))
62+
return
63+
}
64+
65+
if _, err := s.i.FindPermOfRepo(ctx, d.Edges.Repo, u); err != nil {
66+
s.log.Debug("Skip the event. The permission is denied.")
67+
return
68+
}
69+
70+
s.log.Debug("Dispatch a review event.", zap.Int("id", r.ID))
71+
events <- &sse.Event{
72+
Event: "review",
73+
Data: r,
74+
}
5275
}
53-
54-
events <- e
5576
}
77+
5678
if err := s.i.SubscribeEvent(sub); err != nil {
5779
s.log.Check(gb.GetZapLogLevel(err), "Failed to subscribe notification events").Write(zap.Error(err))
5880
gb.ResponseWithError(c, err)
@@ -83,62 +105,8 @@ L:
83105
})
84106
w.Flush()
85107
case e := <-events:
86-
c.Render(-1, sse.Event{
87-
Event: "event",
88-
Data: e,
89-
})
108+
c.Render(-1, e)
90109
w.Flush()
91-
s.log.Debug("server sent event.", zap.Int("event_id", e.ID), zap.String("debug_id", debugID))
92-
}
93-
}
94-
}
95-
96-
// hasPermForEvent checks the user has permission for the event.
97-
func (s *Stream) hasPermForEvent(ctx context.Context, u *ent.User, evt *ent.Event) (bool, error) {
98-
if evt.Kind == event.KindDeployment {
99-
d, err := s.i.FindDeploymentByID(ctx, evt.DeploymentID)
100-
if err != nil {
101-
return false, err
102-
}
103-
104-
if _, err = s.i.FindPermOfRepo(ctx, d.Edges.Repo, u); e.HasErrorCode(err, e.ErrorCodeEntityNotFound) {
105-
return false, nil
106-
} else if err != nil {
107-
return false, err
108110
}
109-
110-
return true, nil
111-
}
112-
113-
if evt.Kind == event.KindReview {
114-
rv, err := s.i.FindReviewByID(ctx, evt.ReviewID)
115-
if err != nil {
116-
return false, err
117-
}
118-
119-
d, err := s.i.FindDeploymentByID(ctx, rv.DeploymentID)
120-
if err != nil {
121-
return false, err
122-
}
123-
124-
if _, err = s.i.FindPermOfRepo(ctx, d.Edges.Repo, u); e.HasErrorCode(err, e.ErrorCodeEntityNotFound) {
125-
return false, nil
126-
} else if err != nil {
127-
return false, err
128-
}
129-
130-
return true, nil
131-
}
132-
133-
return false, fmt.Errorf("The type of event is not \"deployment\" or \"review\".")
134-
}
135-
136-
func randstr() string {
137-
var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
138-
139-
b := make([]rune, 4)
140-
for i := range b {
141-
b[i] = letterRunes[rand.Intn(len(letterRunes))]
142111
}
143-
return string(b)
144112
}

openapi/v1.yaml

Lines changed: 6 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1436,41 +1436,13 @@ paths:
14361436
type: integer
14371437
event:
14381438
type: string
1439+
enum:
1440+
- deployment
1441+
- review
14391442
data:
1440-
type: object
1441-
format: json
1442-
required:
1443-
- id
1444-
- kind
1445-
- type
1446-
- created_at
1447-
- edges
1448-
properties:
1449-
id:
1450-
type: integer
1451-
kind:
1452-
type: string
1453-
enum:
1454-
- deployment
1455-
- review
1456-
type:
1457-
type: string
1458-
enum:
1459-
- created
1460-
- updated
1461-
- deleted
1462-
created_at:
1463-
type: string
1464-
deleted_id:
1465-
type: integer
1466-
description: The ID of deleted resource.
1467-
edges:
1468-
type: object
1469-
properties:
1470-
deployment:
1471-
$ref: '#/components/schemas/Deployment'
1472-
review:
1473-
$ref: '#/components/schemas/Review'
1443+
oneOf:
1444+
- $ref: '#/components/schemas/Deployment'
1445+
- $ref: '#/components/schemas/Review'
14741446
/sync:
14751447
post:
14761448
tags:

ui/src/apis/events.ts

Lines changed: 18 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,36 @@
11
import { instance } from './setting'
22

3-
import { DeploymentData, mapDataToDeployment } from "./deployment"
4-
import { ReviewData, mapDataToReview } from "./review"
5-
import { Deployment, Review, Event, EventKindEnum, EventTypeEnum } from "../models"
3+
import { mapDataToDeployment } from "./deployment"
4+
import { mapDataToReview } from "./review"
5+
import { Deployment, Review } from "../models"
66

7-
interface EventData {
8-
id: number
9-
kind: string
10-
type: string
11-
deleted_id: number
12-
edges: {
13-
deployment?: DeploymentData
14-
review?: ReviewData
15-
}
16-
}
17-
18-
const mapDataToEvent = (data: EventData): Event => {
19-
let kind: EventKindEnum
20-
let type: EventTypeEnum
21-
let deployment: Deployment | undefined
22-
let review: Review | undefined
23-
24-
switch (data.kind) {
25-
case "deployment":
26-
kind = EventKindEnum.Deployment
27-
break
28-
case "review":
29-
kind = EventKindEnum.Review
30-
break
31-
default:
32-
kind = EventKindEnum.Deployment
33-
}
347

35-
switch (data.type) {
36-
case "created":
37-
type = EventTypeEnum.Created
38-
break
39-
case "updated":
40-
type = EventTypeEnum.Updated
41-
break
42-
case "deleted":
43-
type = EventTypeEnum.Deleted
44-
break
45-
default:
46-
type = EventTypeEnum.Created
47-
}
8+
export const subscribeDeploymentEvents = (cb: (deployment: Deployment) => void): EventSource => {
9+
const sse = new EventSource(`${instance}/api/v1/stream/events`, {
10+
withCredentials: true,
11+
})
4812

49-
if (data.edges.deployment) {
50-
deployment = mapDataToDeployment(data.edges.deployment)
51-
}
13+
sse.addEventListener("deployment", (e: any) => {
14+
const data = JSON.parse(e.data)
15+
const deployment = mapDataToDeployment(data)
5216

53-
if (data.edges.review) {
54-
review = mapDataToReview(data.edges.review)
55-
}
17+
cb(deployment)
18+
})
5619

57-
return {
58-
id: data.id,
59-
kind,
60-
type,
61-
deletedId: data.deleted_id,
62-
deployment,
63-
review
64-
}
20+
return sse
6521
}
6622

67-
export const subscribeEvents = (cb: (event: Event) => void): EventSource => {
23+
export const subscribeReviewEvents = (cb: (review: Review) => void): EventSource => {
6824
const sse = new EventSource(`${instance}/api/v1/stream/events`, {
6925
withCredentials: true,
7026
})
7127

72-
sse.addEventListener("event", (e: any) => {
28+
sse.addEventListener("review", (e: any) => {
7329
const data = JSON.parse(e.data)
74-
const event = mapDataToEvent(data)
30+
const review = mapDataToReview(data)
7531

76-
cb(event)
32+
cb(review)
7733
})
7834

7935
return sse
80-
}
36+
}

0 commit comments

Comments
 (0)