mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
Upgrades to slog v3 which includes a small, but backward incompatible API change to the acceptible call arguments when logging. This change allows us to verify via compile time type checking that arguments are correct and won't cause a panic, as was possible in slog v1, which this replaces (v2 was tagged but never used in coder/coder). It also updates dependencies that also use slog and were updated. I've left the `aibridge` dependency as a commit SHA, under the assumption that the team there (cc @pawbana @dannykopping ) will tag and update the dependency soon and on their own schedule. Other dependencies, I pushed new tags.
117 lines
3.9 KiB
Go
117 lines
3.9 KiB
Go
package oauth2provider
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
"cdr.dev/slog/v3"
|
|
|
|
"github.com/coder/coder/v2/coderd/audit"
|
|
"github.com/coder/coder/v2/coderd/database"
|
|
"github.com/coder/coder/v2/coderd/database/dbtime"
|
|
"github.com/coder/coder/v2/coderd/httpapi"
|
|
"github.com/coder/coder/v2/coderd/httpmw"
|
|
"github.com/coder/coder/v2/codersdk"
|
|
)
|
|
|
|
// GetAppSecrets returns an http.HandlerFunc that handles GET /oauth2-provider/apps/{app}/secrets
|
|
func GetAppSecrets(db database.Store) http.HandlerFunc {
|
|
return func(rw http.ResponseWriter, r *http.Request) {
|
|
ctx := r.Context()
|
|
app := httpmw.OAuth2ProviderApp(r)
|
|
dbSecrets, err := db.GetOAuth2ProviderAppSecretsByAppID(ctx, app.ID)
|
|
if err != nil {
|
|
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
|
Message: "Internal error getting OAuth2 client secrets.",
|
|
Detail: err.Error(),
|
|
})
|
|
return
|
|
}
|
|
secrets := []codersdk.OAuth2ProviderAppSecret{}
|
|
for _, secret := range dbSecrets {
|
|
secrets = append(secrets, codersdk.OAuth2ProviderAppSecret{
|
|
ID: secret.ID,
|
|
LastUsedAt: codersdk.NullTime{NullTime: secret.LastUsedAt},
|
|
ClientSecretTruncated: secret.DisplaySecret,
|
|
})
|
|
}
|
|
httpapi.Write(ctx, rw, http.StatusOK, secrets)
|
|
}
|
|
}
|
|
|
|
// CreateAppSecret returns an http.HandlerFunc that handles POST /oauth2-provider/apps/{app}/secrets
|
|
func CreateAppSecret(db database.Store, auditor *audit.Auditor, logger slog.Logger) http.HandlerFunc {
|
|
return func(rw http.ResponseWriter, r *http.Request) {
|
|
var (
|
|
ctx = r.Context()
|
|
app = httpmw.OAuth2ProviderApp(r)
|
|
aReq, commitAudit = audit.InitRequest[database.OAuth2ProviderAppSecret](rw, &audit.RequestParams{
|
|
Audit: *auditor,
|
|
Log: logger,
|
|
Request: r,
|
|
Action: database.AuditActionCreate,
|
|
})
|
|
)
|
|
defer commitAudit()
|
|
secret, err := GenerateSecret()
|
|
if err != nil {
|
|
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
|
Message: "Failed to generate OAuth2 client secret.",
|
|
Detail: err.Error(),
|
|
})
|
|
return
|
|
}
|
|
dbSecret, err := db.InsertOAuth2ProviderAppSecret(ctx, database.InsertOAuth2ProviderAppSecretParams{
|
|
ID: uuid.New(),
|
|
CreatedAt: dbtime.Now(),
|
|
SecretPrefix: []byte(secret.Prefix),
|
|
HashedSecret: secret.Hashed,
|
|
// DisplaySecret is the last six characters of the original unhashed secret.
|
|
// This is done so they can be differentiated and it matches how GitHub
|
|
// displays their client secrets.
|
|
DisplaySecret: secret.Formatted[len(secret.Formatted)-6:],
|
|
AppID: app.ID,
|
|
})
|
|
if err != nil {
|
|
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
|
Message: "Internal error creating OAuth2 client secret.",
|
|
Detail: err.Error(),
|
|
})
|
|
return
|
|
}
|
|
aReq.New = dbSecret
|
|
httpapi.Write(ctx, rw, http.StatusCreated, codersdk.OAuth2ProviderAppSecretFull{
|
|
ID: dbSecret.ID,
|
|
ClientSecretFull: secret.Formatted,
|
|
})
|
|
}
|
|
}
|
|
|
|
// DeleteAppSecret returns an http.HandlerFunc that handles DELETE /oauth2-provider/apps/{app}/secrets/{secretID}
|
|
func DeleteAppSecret(db database.Store, auditor *audit.Auditor, logger slog.Logger) http.HandlerFunc {
|
|
return func(rw http.ResponseWriter, r *http.Request) {
|
|
var (
|
|
ctx = r.Context()
|
|
secret = httpmw.OAuth2ProviderAppSecret(r)
|
|
aReq, commitAudit = audit.InitRequest[database.OAuth2ProviderAppSecret](rw, &audit.RequestParams{
|
|
Audit: *auditor,
|
|
Log: logger,
|
|
Request: r,
|
|
Action: database.AuditActionDelete,
|
|
})
|
|
)
|
|
aReq.Old = secret
|
|
defer commitAudit()
|
|
err := db.DeleteOAuth2ProviderAppSecretByID(ctx, secret.ID)
|
|
if err != nil {
|
|
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
|
Message: "Internal error deleting OAuth2 client secret.",
|
|
Detail: err.Error(),
|
|
})
|
|
return
|
|
}
|
|
rw.WriteHeader(http.StatusNoContent)
|
|
}
|
|
}
|