Skip to content

Commit 4b4d417

Browse files
authored
Merge pull request #199 from joe0BAB/feat/oauth-binary
Wire up oauth API so they can be called from the host-binary / ui
2 parents b8c4745 + 3827ce2 commit 4b4d417

File tree

28 files changed

+8811
-14
lines changed

28 files changed

+8811
-14
lines changed

src/extension/host-binary/Makefile

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,12 @@ post-gen-go-client:
7272
./pkg/generated/go/client/$(DD_API_NAME)/go.* \
7373
./pkg/generated/go/client/$(DD_API_NAME)/git_push.sh
7474

75-
generate: DD_API_NAME=secrets
76-
generate: DD_API_PKGNAME=secretsapi
77-
generate: pre-gen-clients gen-go-client gen-ts-client gen-secrets-api-html post-gen-go-client
75+
generate-sm: DD_API_NAME=secrets
76+
generate-sm: DD_API_PKGNAME=secretsapi
77+
generate-sm: pre-gen-clients gen-go-client gen-secrets-api-html post-gen-go-client
78+
79+
generate-oauth: DD_API_NAME=tools
80+
generate-oauth: DD_API_PKGNAME=oauthapi
81+
generate-oauth: pre-gen-clients gen-go-client gen-secrets-api-html post-gen-go-client
82+
83+
generate: generate-sm generate-oauth
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
openapi: 3.0.3
2+
info:
3+
version: 0.0.0
4+
title: Docker Desktop tools API
5+
x-redocly-package-name: tools
6+
tags:
7+
- name: tools
8+
paths:
9+
/apps:
10+
get:
11+
summary: Lists all app objects.
12+
tags: [ tools ]
13+
operationId: listOAuthApps
14+
responses:
15+
'200':
16+
description: success
17+
content:
18+
application/json:
19+
schema:
20+
type: array
21+
items:
22+
$ref: '#/components/schemas/OAuthApp'
23+
'500':
24+
description: unexpected error
25+
/apps/{app}:
26+
post:
27+
summary: Authorize an app.
28+
tags: [ tools ]
29+
operationId: postOAuthApp
30+
parameters:
31+
- name: app
32+
in: path
33+
required: true
34+
schema:
35+
type: string
36+
- name: scopes
37+
in: query
38+
required: false
39+
schema:
40+
type: string
41+
responses:
42+
'200':
43+
description: success
44+
content:
45+
application/json:
46+
schema:
47+
$ref: '#/components/schemas/AuthResponse'
48+
'500':
49+
description: unexpected error
50+
content:
51+
application/json:
52+
schema:
53+
$ref: '#/components/schemas/AuthResponse'
54+
get:
55+
summary: Returns an app object.
56+
tags: [ tools ]
57+
operationId: getOAuthApp
58+
parameters:
59+
- name: app
60+
in: path
61+
required: true
62+
schema:
63+
type: string
64+
responses:
65+
'200':
66+
description: success
67+
content:
68+
application/json:
69+
schema:
70+
$ref: '#/components/schemas/OAuthApp'
71+
'500':
72+
description: unexpected error
73+
delete:
74+
summary: Unauthorizes an app.
75+
tags: [ tools ]
76+
operationId: deleteOAuthApp
77+
parameters:
78+
- name: app
79+
in: path
80+
required: true
81+
schema:
82+
type: string
83+
responses:
84+
'200':
85+
description: success
86+
'500':
87+
description: unexpected error
88+
/apps/{app}/tools/{tool}:
89+
post:
90+
summary: Add a tool to an app.
91+
tags: [ tools ]
92+
operationId: postOAuthAppTool
93+
parameters:
94+
- name: app
95+
in: path
96+
required: true
97+
schema:
98+
type: string
99+
- name: tool
100+
in: path
101+
required: true
102+
schema:
103+
type: string
104+
responses:
105+
'200':
106+
description: success
107+
'500':
108+
description: unexpected error
109+
delete:
110+
summary: Remove a tool from an app.
111+
tags: [ tools ]
112+
operationId: deleteOAuthAppTool
113+
parameters:
114+
- name: app
115+
in: path
116+
required: true
117+
schema:
118+
type: string
119+
- name: tool
120+
in: path
121+
required: true
122+
schema:
123+
type: string
124+
responses:
125+
'200':
126+
description: success
127+
'500':
128+
description: unexpected error
129+
components:
130+
schemas:
131+
OAuthScopes:
132+
type: object
133+
properties:
134+
name:
135+
type: string
136+
description:
137+
type: string
138+
metadata:
139+
type: array
140+
items:
141+
type: string
142+
OAuthApp:
143+
type: object
144+
properties:
145+
app:
146+
type: string
147+
tools:
148+
type: array
149+
items:
150+
type: string
151+
authorized:
152+
type: boolean
153+
provider:
154+
type: string
155+
scopes:
156+
type: array
157+
items:
158+
$ref: '#/components/schemas/OAuthScopes'
159+
required:
160+
- app
161+
- tools
162+
- authorized
163+
- provider
164+
AuthResponse:
165+
type: object
166+
properties:
167+
browserUrl:
168+
type: string
169+
authType:
170+
type: string

src/extension/host-binary/cmd/main.go

Lines changed: 107 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ import (
44
"context"
55
"encoding/json"
66
"fmt"
7-
"os"
8-
"os/signal"
9-
"syscall"
10-
secretsapi "github.com/docker/labs-ai-tools-for-devs/pkg/generated/go/client/secrets"
117
"github.com/docker/labs-ai-tools-for-devs/pkg/client"
8+
secretsapi "github.com/docker/labs-ai-tools-for-devs/pkg/generated/go/client/secrets"
129
"github.com/docker/labs-ai-tools-for-devs/pkg/paths"
1310
"github.com/spf13/cobra"
11+
"os"
12+
"os/signal"
13+
"syscall"
1414
)
1515

1616
func main() {
@@ -20,6 +20,9 @@ func main() {
2020
cmd := AddSecret(ctx)
2121
cmd.AddCommand(ListSecrets(ctx))
2222
cmd.AddCommand(DeleteSecret(ctx))
23+
cmd.AddCommand(AuthorizeApp(ctx))
24+
cmd.AddCommand(UnauthorizeApp(ctx))
25+
cmd.AddCommand(ListOAuthApps(ctx))
2326
if err := cmd.Execute(); err != nil {
2427
fmt.Println(err)
2528
os.Exit(1)
@@ -45,6 +48,105 @@ func newApiClient() (client.ApiClient, error) {
4548
return client.NewApiClient(p), nil
4649
}
4750

51+
func newOAuthApiClient() (client.OAuthApiClient, error) {
52+
p, err := paths.GetToolsApiSocketPath()
53+
if err != nil {
54+
return nil, err
55+
}
56+
return client.NewOAuthApiClient(p), nil
57+
}
58+
59+
func ListOAuthApps(ctx context.Context) *cobra.Command {
60+
cmd := &cobra.Command{
61+
Use: "list-oauth-apps",
62+
Short: "List all OAuth apps",
63+
Args: cobra.NoArgs,
64+
RunE: func(*cobra.Command, []string) error {
65+
return runListOAuthApps(ctx)
66+
},
67+
}
68+
return cmd
69+
}
70+
71+
func runListOAuthApps(ctx context.Context) error {
72+
c, err := newOAuthApiClient()
73+
if err != nil {
74+
return err
75+
}
76+
apps, err := c.ListOAuthApps(ctx)
77+
if err != nil {
78+
return err
79+
}
80+
return json.NewEncoder(os.Stdout).Encode(apps)
81+
}
82+
83+
type authorizeOptions struct {
84+
Name string
85+
Scopes string
86+
}
87+
88+
func AuthorizeApp(ctx context.Context) *cobra.Command {
89+
opts := &authorizeOptions{}
90+
cmd := &cobra.Command{
91+
Use: "authorize",
92+
Short: "Authorize an OAuth app",
93+
Args: cobra.NoArgs,
94+
RunE: func(*cobra.Command, []string) error {
95+
return runAuthorizeApp(ctx, *opts)
96+
},
97+
}
98+
flags := cmd.Flags()
99+
flags.StringVarP(&opts.Name, "name", "n", "", "Name of the OAuth app")
100+
_ = cmd.MarkFlagRequired("name")
101+
flags.StringVarP(&opts.Scopes, "scopes", "s", "", "Scopes for the OAuth app")
102+
return cmd
103+
}
104+
105+
func runAuthorizeApp(ctx context.Context, opts authorizeOptions) error {
106+
c, err := newOAuthApiClient()
107+
if err != nil {
108+
return err
109+
}
110+
authResponse, err := c.PostOAuthApp(ctx, opts.Name, opts.Scopes)
111+
if err != nil {
112+
return err
113+
}
114+
return json.NewEncoder(os.Stdout).Encode(authResponse)
115+
}
116+
117+
type unauthorizeOptions struct {
118+
Name string
119+
}
120+
121+
func UnauthorizeApp(ctx context.Context) *cobra.Command {
122+
opts := &unauthorizeOptions{}
123+
cmd := &cobra.Command{
124+
Use: "unauthorize",
125+
Short: "Unauthorize an OAuth app",
126+
Args: cobra.NoArgs,
127+
RunE: func(*cobra.Command, []string) error {
128+
return runUnauthorizeApp(ctx, *opts)
129+
},
130+
}
131+
flags := cmd.Flags()
132+
flags.StringVarP(&opts.Name, "name", "n", "", "Name of the OAuth app")
133+
_ = cmd.MarkFlagRequired("name")
134+
return cmd
135+
}
136+
137+
func runUnauthorizeApp(ctx context.Context, opts unauthorizeOptions) error {
138+
c, err := newOAuthApiClient()
139+
if err != nil {
140+
return err
141+
}
142+
err = c.DeleteOAuthApp(ctx, opts.Name)
143+
if err != nil {
144+
return err
145+
}
146+
fmt.Printf("App %s has been unauthorised\n", opts.Name)
147+
return nil
148+
}
149+
48150
type addOptions struct {
49151
Name string
50152
Value string
@@ -87,7 +189,7 @@ func ListSecrets(ctx context.Context) *cobra.Command {
87189
func DeleteSecret(ctx context.Context) *cobra.Command {
88190
opts := &deleteOptions{}
89191
cmd := &cobra.Command{
90-
Use: "delete",
192+
Use: "delete",
91193
Short: "Delete a secret",
92194
Args: cobra.NoArgs,
93195
RunE: func(*cobra.Command, []string) error {

src/extension/host-binary/pkg/client/client.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,6 @@ func NewApiClient(socketPath string) ApiClient {
3636
}
3737
}
3838

39-
type Secret struct {
40-
Name string
41-
Value string
42-
Policies []string
43-
}
44-
4539
func (d apiClientImpl) SetSecret(ctx context.Context, s secretsapi.Secret) error {
4640
apiReq := d.SecretsApi.SetJfsSecret(ctx)
4741
req := secretsapi.NewSecret(s.Name, s.Value, s.Policies)

src/extension/host-binary/pkg/client/conn.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package client
33
import (
44
"context"
55
"github.com/docker/labs-ai-tools-for-devs/pkg/generated/go/client/secrets"
6+
oauthapi "github.com/docker/labs-ai-tools-for-devs/pkg/generated/go/client/tools"
67
"net"
78
"net/http"
89
)
@@ -25,3 +26,17 @@ func GetConfiguration(addr string) *secretsapi.Configuration {
2526
}
2627
return cfg
2728
}
29+
30+
func GetOAuthConfiguration(addr string) *oauthapi.Configuration {
31+
cfg := oauthapi.NewConfiguration()
32+
cfg.Scheme = HTTPProtocol
33+
cfg.Host = DummyHost
34+
cfg.HTTPClient = &http.Client{
35+
Transport: &http.Transport{
36+
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
37+
return DialSocket(addr)
38+
},
39+
},
40+
}
41+
return cfg
42+
}

0 commit comments

Comments
 (0)