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

Commit 98ff6a3

Browse files
author
Noah Hanjun Lee
authored
feat: limit users by approved orgs (#111)
* Fix the type of payload * Fix to prevent logic when it hits the limit * Update to check login that is in members
1 parent 5827e5f commit 98ff6a3

File tree

12 files changed

+186
-51
lines changed

12 files changed

+186
-51
lines changed

cmd/server/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ type (
2525
ServerProxyProto string `default:"https" split_words:"true"`
2626

2727
OrganizationEntries []string `split_words:"true"`
28+
MemberEntries []string `split_words:"true"`
2829
AdminUsers []string `split_words:"true"`
2930

3031
License string `split_words:"true"`

cmd/server/main.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -133,13 +133,14 @@ func newChatConfig(c *Config) *server.ChatConfig {
133133
func NewInteractor(c *Config) server.Interactor {
134134
return interactor.NewInteractor(
135135
&interactor.InteractorConfig{
136-
ServerHost: c.ServerHost,
137-
ServerProto: c.ServerProto,
138-
OrgEntries: c.OrganizationEntries,
139-
AdminUsers: c.AdminUsers,
140-
LicenseKey: c.License,
141-
Store: newStore(c),
142-
SCM: newSCM(c),
136+
ServerHost: c.ServerHost,
137+
ServerProto: c.ServerProto,
138+
OrgEntries: c.OrganizationEntries,
139+
MemberEntries: c.MemberEntries,
140+
AdminUsers: c.AdminUsers,
141+
LicenseKey: c.License,
142+
Store: newStore(c),
143+
SCM: newSCM(c),
143144
},
144145
)
145146
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# GITPLOY_MEMBER_ENTRIES
2+
3+
Optional comma-separated list of accounts, used to limit to users in this list, or users that are members of organizations included in this list.
4+
5+
```
6+
GITPLOY_MEMBER_ENTRIES=octocat,gitploy-io
7+
```

docs/references/configurations.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Index of server configuration settings:
88
* [GITPLOY_PROXY_SERVER_PROTO](./GITPLOY_PROXY_SERVER_PROTO.md)
99
* [GITPLOY_WEBHOOK_SECRET](./GITPLOY_WEBHOOK_SECRET.md)
1010
* [GITPLOY_ORGANIZATION_ENTRIES](./GITPLOY_ORGANIZATION_ENTRIES.md)
11+
* [GITPLOY_MEMBER_ENTRIES](./GITPLOY_MEMBER_ENTRIES.md)
1112
* [GITPLOY_ADMIN_USERS](./GITPLOY_ADMIN_USERS.md)
1213
* [GITPLOY_GITHUB_CLIENT_ID](./GITPLOY_GITHUB_CLIENT_ID.md)
1314
* [GITPLOY_GITHUB_CLIENT_SECRET](./GITPLOY_GITHUB_CLIENT_SECRET.md)

internal/interactor/interactor.go

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ type (
1111
ServerHost string
1212
ServerProto string
1313

14-
orgEntries []string
14+
orgEntries []string
15+
memberEntries []string
1516
// Admin Users
1617
admins []string
1718

@@ -32,8 +33,9 @@ type (
3233
ServerHost string
3334
ServerProto string
3435

35-
OrgEntries []string
36-
AdminUsers []string
36+
OrgEntries []string
37+
MemberEntries []string
38+
AdminUsers []string
3739

3840
LicenseKey string
3941

@@ -44,16 +46,17 @@ type (
4446

4547
func NewInteractor(c *InteractorConfig) *Interactor {
4648
i := &Interactor{
47-
ServerHost: c.ServerHost,
48-
ServerProto: c.ServerProto,
49-
orgEntries: c.OrgEntries,
50-
admins: c.AdminUsers,
51-
licenseKey: c.LicenseKey,
52-
Store: c.Store,
53-
SCM: c.SCM,
54-
stopCh: make(chan struct{}),
55-
events: evbus.New(),
56-
log: zap.L().Named("interactor"),
49+
ServerHost: c.ServerHost,
50+
ServerProto: c.ServerProto,
51+
orgEntries: c.OrgEntries,
52+
memberEntries: c.MemberEntries,
53+
admins: c.AdminUsers,
54+
licenseKey: c.LicenseKey,
55+
Store: c.Store,
56+
SCM: c.SCM,
57+
stopCh: make(chan struct{}),
58+
events: evbus.New(),
59+
log: zap.L().Named("interactor"),
5760
}
5861

5962
go func() {

internal/interactor/interface.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@ type (
7373
}
7474

7575
SCM interface {
76-
GetUser(ctx context.Context, token string) (*vo.RemoteUser, error)
76+
GetRemoteUserByToken(ctx context.Context, token string) (*vo.RemoteUser, error)
77+
ListRemoteOrgsByToken(ctx context.Context, token string) ([]string, error)
7778

7879
ListRemoteRepos(ctx context.Context, u *ent.User) ([]*vo.RemoteRepo, error)
7980

internal/interactor/mock/pkg.go

Lines changed: 29 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/interactor/user.go

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,8 @@ package interactor
22

33
import (
44
"context"
5-
6-
"github.com/gitploy-io/gitploy/vo"
75
)
86

9-
func (i *Interactor) GetRemoteUserByToken(ctx context.Context, token string) (*vo.RemoteUser, error) {
10-
return i.SCM.GetUser(ctx, token)
11-
}
12-
137
func (i *Interactor) IsAdminUser(ctx context.Context, login string) bool {
148
for _, admin := range i.admins {
159
if login == admin {
@@ -19,3 +13,29 @@ func (i *Interactor) IsAdminUser(ctx context.Context, login string) bool {
1913

2014
return false
2115
}
16+
17+
func (i *Interactor) IsEntryMember(ctx context.Context, login string) bool {
18+
if i.memberEntries == nil {
19+
return true
20+
}
21+
22+
for _, m := range i.memberEntries {
23+
if login == m {
24+
return true
25+
}
26+
}
27+
28+
return false
29+
}
30+
31+
func (i *Interactor) IsOrgMember(ctx context.Context, orgs []string) bool {
32+
for _, o := range orgs {
33+
for _, entry := range i.memberEntries {
34+
if o == entry {
35+
return true
36+
}
37+
}
38+
}
39+
40+
return false
41+
}

internal/interactor/user_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,51 @@ func TestInteractor_IsAdminUser(t *testing.T) {
1717
}
1818
})
1919
}
20+
21+
func TestInteractor_IsEntryMember(t *testing.T) {
22+
t.Run("Return false when the user's login is not included.", func(t *testing.T) {
23+
i := &Interactor{
24+
memberEntries: []string{"octocat"},
25+
}
26+
27+
want := false
28+
if ret := i.IsEntryMember(context.Background(), "coco"); ret != want {
29+
t.Fatalf("IsEntryMember = %v, wanted %v", ret, want)
30+
}
31+
})
32+
33+
t.Run("Return true when the user's login is included.", func(t *testing.T) {
34+
i := &Interactor{
35+
memberEntries: []string{"octocat"},
36+
}
37+
38+
want := true
39+
if ret := i.IsEntryMember(context.Background(), "octocat"); ret != want {
40+
t.Fatalf("IsEntryMember = %v, wanted %v", ret, want)
41+
}
42+
})
43+
}
44+
45+
func TestInteractor_IsOrgMember(t *testing.T) {
46+
t.Run("Return false when the org is not included.", func(t *testing.T) {
47+
i := &Interactor{
48+
memberEntries: []string{"gitploy-io"},
49+
}
50+
51+
want := false
52+
if ret := i.IsOrgMember(context.Background(), []string{"github"}); ret != want {
53+
t.Fatalf("IsEntryMember = %v, wanted %v", ret, want)
54+
}
55+
})
56+
57+
t.Run("Return true when the org is included.", func(t *testing.T) {
58+
i := &Interactor{
59+
memberEntries: []string{"gitploy-io"},
60+
}
61+
62+
want := true
63+
if ret := i.IsOrgMember(context.Background(), []string{"gitploy-io"}); ret != want {
64+
t.Fatalf("IsEntryMember = %v, wanted %v", ret, want)
65+
}
66+
})
67+
}

internal/pkg/github/web.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ import (
44
"context"
55

66
"github.com/gitploy-io/gitploy/vo"
7+
"github.com/google/go-github/v32/github"
78
)
89

9-
func (g *Github) GetUser(ctx context.Context, token string) (*vo.RemoteUser, error) {
10+
func (g *Github) GetRemoteUserByToken(ctx context.Context, token string) (*vo.RemoteUser, error) {
1011
c := g.Client(ctx, token)
1112

1213
u, _, err := c.Users.Get(ctx, "")
@@ -16,3 +17,20 @@ func (g *Github) GetUser(ctx context.Context, token string) (*vo.RemoteUser, err
1617

1718
return mapGithubUserToUser(u), err
1819
}
20+
21+
func (g *Github) ListRemoteOrgsByToken(ctx context.Context, token string) ([]string, error) {
22+
// TODO: List all orgs.
23+
orgs, _, err := g.Client(ctx, token).
24+
Organizations.
25+
List(ctx, "", &github.ListOptions{})
26+
if err != nil {
27+
return nil, err
28+
}
29+
30+
ret := []string{}
31+
for _, o := range orgs {
32+
ret = append(ret, *o.Login)
33+
}
34+
35+
return ret, nil
36+
}

0 commit comments

Comments
 (0)