Files
Jonathan Miller c572fcfe04
PR RC Release / Build RC Release (pull_request) Failing after 0s
Branch Policy Check / Verify merge target (pull_request) Failing after 0s
chore(core): rename Go module from code.gitea.io/gitea to MokoGitea namespace
Rename the Go module path from code.gitea.io/gitea to
git.mokoconsulting.tech/MokoConsulting/MokoGitea across the entire
codebase.

Scope:
- go.mod module declaration
- 2,235 Go source files (import paths)
- Dockerfile WORKDIR and COPY paths
- Swagger API templates
- golangci.yml linter config

External dependencies (code.gitea.io/gitea-vet, code.gitea.io/sdk/gitea,
gitea.com/gitea/act, etc.) are intentionally NOT renamed — they are
separate upstream modules.

Closes #132

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-25 00:22:38 -05:00

115 lines
3.3 KiB
Go

// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package oauth2
import (
"context"
"time"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
user_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"github.com/markbates/goth"
"golang.org/x/oauth2"
)
// Sync causes this OAuth2 source to synchronize its users with the db.
func (source *Source) Sync(ctx context.Context, updateExisting bool) error {
log.Trace("Doing: SyncExternalUsers[%s] %d", source.AuthSource.Name, source.AuthSource.ID)
if !updateExisting {
log.Info("SyncExternalUsers[%s] not running since updateExisting is false", source.AuthSource.Name)
return nil
}
provider, err := createProvider(source.AuthSource.Name, source)
if err != nil {
return err
}
if !provider.RefreshTokenAvailable() {
log.Trace("SyncExternalUsers[%s] provider doesn't support refresh tokens, can't synchronize", source.AuthSource.Name)
return nil
}
opts := user_model.FindExternalUserOptions{
HasRefreshToken: true,
Expired: true,
LoginSourceID: source.AuthSource.ID,
}
return user_model.IterateExternalLogin(ctx, opts, func(ctx context.Context, u *user_model.ExternalLoginUser) error {
return source.refresh(ctx, provider, u)
})
}
func (source *Source) refresh(ctx context.Context, provider goth.Provider, u *user_model.ExternalLoginUser) error {
log.Trace("Syncing login_source_id=%d external_id=%s expiration=%s", u.LoginSourceID, u.ExternalID, u.ExpiresAt)
shouldDisable := false
token, err := provider.RefreshToken(u.RefreshToken)
if err != nil {
if err, ok := err.(*oauth2.RetrieveError); ok && err.ErrorCode == "invalid_grant" {
// this signals that the token is not valid and the user should be disabled
shouldDisable = true
} else {
return err
}
}
user := &user_model.User{
LoginName: u.ExternalID,
LoginType: auth.OAuth2,
LoginSource: u.LoginSourceID,
}
hasUser, err := user_model.GetIndividualUser(ctx, user)
if err != nil {
return err
}
// If the grant is no longer valid, disable the user and
// delete local tokens. If the OAuth2 provider still
// recognizes them as a valid user, they will be able to login
// via their provider and reactivate their account.
if shouldDisable {
log.Info("SyncExternalUsers[%s] disabling user %d", source.AuthSource.Name, user.ID)
return db.WithTx(ctx, func(ctx context.Context) error {
if hasUser {
user.IsActive = false
err := user_model.UpdateUserCols(ctx, user, "is_active")
if err != nil {
return err
}
}
// Delete stored tokens, since they are invalid. This
// also provents us from checking this in subsequent runs.
u.AccessToken = ""
u.RefreshToken = ""
u.ExpiresAt = time.Time{}
return user_model.UpdateExternalUserByExternalID(ctx, u)
})
}
// Otherwise, update the tokens
u.AccessToken = token.AccessToken
u.ExpiresAt = token.Expiry
// Some providers only update access tokens provide a new
// refresh token, so avoid updating it if it's empty
if token.RefreshToken != "" {
u.RefreshToken = token.RefreshToken
}
err = user_model.UpdateExternalUserByExternalID(ctx, u)
return err
}