chore: add github.com user id association (#14045)

* chore: add github.com user id association

This will eventually be used to show an indicator in the UI
to star the repository if you've been using Coder for a while
and have not starred the repo.

If you have, we'll never show a thing!

* gen

* Fix model query

* Fix linting

* Ignore auditing github.com user id

* Add test

* Fix gh url var name

* Update migration

* Update coderd/database/dbauthz/dbauthz.go

Co-authored-by: Steven Masley <Emyrk@users.noreply.github.com>

* Fix updating to when the token changes

* Fix migration

---------

Co-authored-by: Steven Masley <Emyrk@users.noreply.github.com>
This commit is contained in:
Kyle Carberry
2024-08-02 12:49:36 -04:00
committed by GitHub
co-authored by Steven Masley
parent 4d4d27c509
commit 6e36082b0f
25 changed files with 222 additions and 37 deletions
+26 -6
View File
@@ -31,6 +31,7 @@ import (
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/database/dbauthz"
"github.com/coder/coder/v2/coderd/database/dbtime"
"github.com/coder/coder/v2/coderd/externalauth"
"github.com/coder/coder/v2/coderd/httpapi"
"github.com/coder/coder/v2/coderd/httpmw"
"github.com/coder/coder/v2/coderd/promoauth"
@@ -661,7 +662,7 @@ func (api *API) userOAuth2Github(rw http.ResponseWriter, r *http.Request) {
}).SetInitAuditRequest(func(params *audit.RequestParams) (*audit.Request[database.User], func()) {
return audit.InitRequest[database.User](rw, params)
})
cookies, key, err := api.oauthLogin(r, params)
cookies, user, key, err := api.oauthLogin(r, params)
defer params.CommitAuditLogs()
var httpErr httpError
if xerrors.As(err, &httpErr) {
@@ -676,6 +677,25 @@ func (api *API) userOAuth2Github(rw http.ResponseWriter, r *http.Request) {
})
return
}
// If the user is logging in with github.com we update their associated
// GitHub user ID to the new one.
if externalauth.IsGithubDotComURL(api.GithubOAuth2Config.AuthCodeURL("")) && user.GithubComUserID.Int64 != ghUser.GetID() {
err = api.Database.UpdateUserGithubComUserID(ctx, database.UpdateUserGithubComUserIDParams{
ID: user.ID,
GithubComUserID: sql.NullInt64{
Int64: ghUser.GetID(),
Valid: true,
},
})
if err != nil {
logger.Error(ctx, "oauth2: unable to update user github id", slog.F("user", user.Username), slog.Error(err))
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Failed to update user GitHub ID.",
Detail: err.Error(),
})
return
}
}
aReq.New = key
aReq.UserID = key.UserID
@@ -1030,7 +1050,7 @@ func (api *API) userOIDC(rw http.ResponseWriter, r *http.Request) {
}).SetInitAuditRequest(func(params *audit.RequestParams) (*audit.Request[database.User], func()) {
return audit.InitRequest[database.User](rw, params)
})
cookies, key, err := api.oauthLogin(r, params)
cookies, user, key, err := api.oauthLogin(r, params)
defer params.CommitAuditLogs()
var httpErr httpError
if xerrors.As(err, &httpErr) {
@@ -1320,7 +1340,7 @@ func (e httpError) Error() string {
return e.msg
}
func (api *API) oauthLogin(r *http.Request, params *oauthLoginParams) ([]*http.Cookie, database.APIKey, error) {
func (api *API) oauthLogin(r *http.Request, params *oauthLoginParams) ([]*http.Cookie, database.User, database.APIKey, error) {
var (
ctx = r.Context()
user database.User
@@ -1610,7 +1630,7 @@ func (api *API) oauthLogin(r *http.Request, params *oauthLoginParams) ([]*http.C
return nil
}, nil)
if err != nil {
return nil, database.APIKey{}, xerrors.Errorf("in tx: %w", err)
return nil, database.User{}, database.APIKey{}, xerrors.Errorf("in tx: %w", err)
}
var key database.APIKey
@@ -1647,13 +1667,13 @@ func (api *API) oauthLogin(r *http.Request, params *oauthLoginParams) ([]*http.C
RemoteAddr: r.RemoteAddr,
})
if err != nil {
return nil, database.APIKey{}, xerrors.Errorf("create API key: %w", err)
return nil, database.User{}, database.APIKey{}, xerrors.Errorf("create API key: %w", err)
}
cookies = append(cookies, cookie)
key = *newKey
}
return cookies, key, nil
return cookies, user, key, nil
}
// convertUserToOauth will convert a user from password base loginType to