- Notifications
You must be signed in to change notification settings - Fork928
POST license API endpoint#3570
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Changes fromall commits
b9d5915
ddb7332
a2189e0
0d698e2
b3288e4
0fbe130
a590d75
4d6dfcb
ba9167e
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -27,6 +27,11 @@ func AuthorizeFilter[O rbac.Objecter](api *API, r *http.Request, action rbac.Act | ||
return objects, nil | ||
} | ||
type HTTPAuthorizer struct { | ||
Authorizer rbac.Authorizer | ||
Logger slog.Logger | ||
spikecurtis marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
} | ||
// Authorize will return false if the user is not authorized to do the action. | ||
// This function will log appropriately, but the caller must return an | ||
// error to the api client. | ||
@@ -36,14 +41,26 @@ func AuthorizeFilter[O rbac.Objecter](api *API, r *http.Request, action rbac.Act | ||
//return | ||
//} | ||
func (api *API) Authorize(r *http.Request, action rbac.Action, object rbac.Objecter) bool { | ||
return api.httpAuth.Authorize(r, action, object) | ||
} | ||
// Authorize will return false if the user is not authorized to do the action. | ||
// This function will log appropriately, but the caller must return an | ||
// error to the api client. | ||
// Eg: | ||
//if !h.Authorize(...) { | ||
//httpapi.Forbidden(rw) | ||
//return | ||
//} | ||
func (h *HTTPAuthorizer) Authorize(r *http.Request, action rbac.Action, object rbac.Objecter) bool { | ||
roles := httpmw.AuthorizationUserRoles(r) | ||
err :=h.Authorizer.ByRoleName(r.Context(), roles.ID.String(), roles.Roles, action, object.RBACObject()) | ||
if err != nil { | ||
// Log the errors for debugging | ||
internalError := new(rbac.UnauthorizedError) | ||
logger :=h.Logger | ||
if xerrors.As(err, internalError) { | ||
logger =h.Logger.With(slog.F("internal", internalError.Internal())) | ||
} | ||
// Log information for debugging. This will be very helpful | ||
// in the early days | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -66,6 +66,7 @@ type Options struct { | ||
Telemetry telemetry.Reporter | ||
TURNServer*turnconn.Server | ||
TracerProvider*sdktrace.TracerProvider | ||
LicenseHandler http.Handler | ||
} | ||
// New constructs a Coder API handler. | ||
@@ -92,6 +93,9 @@ func New(options *Options) *API { | ||
ifoptions.PrometheusRegistry==nil { | ||
options.PrometheusRegistry=prometheus.NewRegistry() | ||
} | ||
ifoptions.LicenseHandler==nil { | ||
options.LicenseHandler=licenses() | ||
} | ||
siteCacheDir:=options.CacheDir | ||
ifsiteCacheDir!="" { | ||
@@ -107,6 +111,10 @@ func New(options *Options) *API { | ||
Options:options, | ||
Handler:r, | ||
siteHandler:site.Handler(site.FS(),binFS), | ||
httpAuth:&HTTPAuthorizer{ | ||
Authorizer:options.Authorizer, | ||
Logger:options.Logger, | ||
}, | ||
} | ||
api.workspaceAgentCache=wsconncache.New(api.dialWorkspaceAgent,0) | ||
oauthConfigs:=&httpmw.OAuth2Configs{ | ||
@@ -395,6 +403,10 @@ func New(options *Options) *API { | ||
r.Use(apiKeyMiddleware) | ||
r.Get("/",entitlements) | ||
}) | ||
r.Route("/licenses",func(r chi.Router) { | ||
r.Use(apiKeyMiddleware) | ||
r.Mount("/",options.LicenseHandler) | ||
spikecurtis marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
}) | ||
}) | ||
r.NotFound(compressHandler(http.HandlerFunc(api.siteHandler.ServeHTTP)).ServeHTTP) | ||
@@ -409,6 +421,7 @@ type API struct { | ||
websocketWaitMutex sync.Mutex | ||
websocketWaitGroup sync.WaitGroup | ||
workspaceAgentCache*wsconncache.Cache | ||
httpAuth*HTTPAuthorizer | ||
} | ||
// Close waits for all WebSocket connections to drain before returning. | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -73,6 +73,7 @@ type Options struct { | ||
// IncludeProvisionerD when true means to start an in-memory provisionerD | ||
IncludeProvisionerDbool | ||
APIBuilderfunc(*coderd.Options)*coderd.API | ||
kylecarbs marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
} | ||
// New constructs a codersdk client connected to an in-memory API instance. | ||
@@ -122,6 +123,9 @@ func newWithCloser(t *testing.T, options *Options) (*codersdk.Client, io.Closer) | ||
close(options.AutobuildStats) | ||
}) | ||
} | ||
ifoptions.APIBuilder==nil { | ||
options.APIBuilder=coderd.New | ||
} | ||
// This can be hotswapped for a live database instance. | ||
db:=databasefake.New() | ||
@@ -177,7 +181,7 @@ func newWithCloser(t *testing.T, options *Options) (*codersdk.Client, io.Closer) | ||
}) | ||
// We set the handler after server creation for the access URL. | ||
coderAPI:=options.APIBuilder(&coderd.Options{ | ||
AgentConnectionUpdateFrequency:150*time.Millisecond, | ||
// Force a long disconnection timeout to ensure | ||
// agents are not marked as disconnected during slow tests. | ||
Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.
Uh oh!
There was an error while loading.Please reload this page.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
-- Valid licenses don't fit into old format, so delete all data | ||
DELETEFROM licenses; | ||
ALTERTABLE licenses DROP COLUMN jwt; | ||
ALTERTABLE licenses RENAME COLUMN uploaded_at to created_at; | ||
ALTERTABLE licenses ADD COLUMN license jsonbNOT NULL; | ||
ALTERTABLE licenses DROP COLUMN exp; | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
-- No valid licenses should exist, but to be sure, drop all rows | ||
DELETEFROM licenses; | ||
ALTERTABLE licenses DROP COLUMN license; | ||
ALTERTABLE licenses RENAME COLUMN created_at to uploaded_at; | ||
ALTERTABLE licenses ADD COLUMN jwttextNOT NULL; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. In | ||
-- prevent adding the same license more than once | ||
ALTERTABLE licenses ADDCONSTRAINT licenses_jwt_key UNIQUE (jwt); | ||
ALTERTABLE licenses ADD COLUMN exptimestamp with time zoneNOT NULL; | ||
COMMENT ON COLUMN licenses.exp IS'exp tracks the claim of the same name in the JWT, and we include it here so that we can easily query for licenses that have not yet expired.'; | ||
Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.
Uh oh!
There was an error while loading.Please reload this page.
Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.