mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2025-02-04 18:21:06 +02:00
Identify users using their remote ID (#1732)
This commit is contained in:
parent
02cfbc8cbf
commit
6d2240b2e6
@ -65,7 +65,7 @@ func HandleAuth(c *gin.Context) {
|
||||
config := ToConfig(c)
|
||||
|
||||
// get the user from the database
|
||||
u, err := _store.GetUserLogin(tmpuser.Login)
|
||||
u, err := _store.GetUserRemoteID(tmpuser.ForgeRemoteID, tmpuser.Login)
|
||||
if err != nil {
|
||||
if !errors.Is(err, types.RecordNotExist) {
|
||||
_ = c.AbortWithError(http.StatusInternalServerError, err)
|
||||
@ -92,11 +92,12 @@ func HandleAuth(c *gin.Context) {
|
||||
|
||||
// create the user account
|
||||
u = &model.User{
|
||||
Login: tmpuser.Login,
|
||||
Token: tmpuser.Token,
|
||||
Secret: tmpuser.Secret,
|
||||
Email: tmpuser.Email,
|
||||
Avatar: tmpuser.Avatar,
|
||||
Login: tmpuser.Login,
|
||||
ForgeRemoteID: tmpuser.ForgeRemoteID,
|
||||
Token: tmpuser.Token,
|
||||
Secret: tmpuser.Secret,
|
||||
Email: tmpuser.Email,
|
||||
Avatar: tmpuser.Avatar,
|
||||
Hash: base32.StdEncoding.EncodeToString(
|
||||
securecookie.GenerateRandomKey(32),
|
||||
),
|
||||
@ -115,6 +116,8 @@ func HandleAuth(c *gin.Context) {
|
||||
u.Secret = tmpuser.Secret
|
||||
u.Email = tmpuser.Email
|
||||
u.Avatar = tmpuser.Avatar
|
||||
u.ForgeRemoteID = tmpuser.ForgeRemoteID
|
||||
u.Login = tmpuser.Login
|
||||
u.Admin = u.Admin || config.IsAdmin(tmpuser)
|
||||
|
||||
// if self-registration is enabled for whitelisted organizations we need to
|
||||
|
@ -118,11 +118,12 @@ func cloneLink(repo *internal.Repo) string {
|
||||
// structure to the Woodpecker User structure.
|
||||
func convertUser(from *internal.Account, token *oauth2.Token) *model.User {
|
||||
return &model.User{
|
||||
Login: from.Login,
|
||||
Token: token.AccessToken,
|
||||
Secret: token.RefreshToken,
|
||||
Expiry: token.Expiry.UTC().Unix(),
|
||||
Avatar: from.Links.Avatar.Href,
|
||||
Login: from.Login,
|
||||
Token: token.AccessToken,
|
||||
Secret: token.RefreshToken,
|
||||
Expiry: token.Expiry.UTC().Unix(),
|
||||
Avatar: from.Links.Avatar.Href,
|
||||
ForgeRemoteID: model.ForgeRemoteID(fmt.Sprint(from.ID)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
)
|
||||
|
||||
type Account struct {
|
||||
ID int64 `json:"id"`
|
||||
Login string `json:"username"`
|
||||
Name string `json:"display_name"`
|
||||
Type string `json:"type"`
|
||||
|
@ -121,10 +121,11 @@ func convertPushHook(hook *internal.PostHook, baseURL string) *model.Pipeline {
|
||||
// structure to the Woodpecker User structure.
|
||||
func convertUser(from *internal.User, token *oauth.AccessToken) *model.User {
|
||||
return &model.User{
|
||||
Login: from.Slug,
|
||||
Token: token.Token,
|
||||
Email: from.EmailAddress,
|
||||
Avatar: avatarLink(from.EmailAddress),
|
||||
Login: from.Slug,
|
||||
Token: token.Token,
|
||||
Email: from.EmailAddress,
|
||||
Avatar: avatarLink(from.EmailAddress),
|
||||
ForgeRemoteID: model.ForgeRemoteID(fmt.Sprint(from.ID)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,29 +70,27 @@ func NewClientWithToken(ctx context.Context, url string, consumer *oauth.Consume
|
||||
}
|
||||
|
||||
func (c *Client) FindCurrentUser() (*User, error) {
|
||||
CurrentUserIDResponse, err := c.doGet(fmt.Sprintf(currentUserID, c.base))
|
||||
if CurrentUserIDResponse != nil {
|
||||
defer CurrentUserIDResponse.Body.Close()
|
||||
}
|
||||
currentUserIDResponse, err := c.doGet(fmt.Sprintf(currentUserID, c.base))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer currentUserIDResponse.Body.Close()
|
||||
|
||||
bits, err := io.ReadAll(CurrentUserIDResponse.Body)
|
||||
bits, err := io.ReadAll(currentUserIDResponse.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
login := string(bits)
|
||||
|
||||
CurrentUserResponse, err := c.doGet(fmt.Sprintf(pathUser, c.base, login))
|
||||
if CurrentUserResponse != nil {
|
||||
defer CurrentUserResponse.Body.Close()
|
||||
currentUserResponse, err := c.doGet(fmt.Sprintf(pathUser, c.base, login))
|
||||
if currentUserResponse != nil {
|
||||
defer currentUserResponse.Body.Close()
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
contents, err := io.ReadAll(CurrentUserResponse.Body)
|
||||
contents, err := io.ReadAll(currentUserResponse.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -143,12 +143,13 @@ func (c *Gitea) Login(ctx context.Context, w http.ResponseWriter, req *http.Requ
|
||||
}
|
||||
|
||||
return &model.User{
|
||||
Token: token.AccessToken,
|
||||
Secret: token.RefreshToken,
|
||||
Expiry: token.Expiry.UTC().Unix(),
|
||||
Login: account.UserName,
|
||||
Email: account.Email,
|
||||
Avatar: expandAvatar(c.URL, account.AvatarURL),
|
||||
Token: token.AccessToken,
|
||||
Secret: token.RefreshToken,
|
||||
Expiry: token.Expiry.UTC().Unix(),
|
||||
Login: account.UserName,
|
||||
Email: account.Email,
|
||||
ForgeRemoteID: model.ForgeRemoteID(fmt.Sprint(account.ID)),
|
||||
Avatar: expandAvatar(c.URL, account.AvatarURL),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -129,10 +129,11 @@ func (c *client) Login(ctx context.Context, res http.ResponseWriter, req *http.R
|
||||
}
|
||||
|
||||
return &model.User{
|
||||
Login: *user.Login,
|
||||
Email: *email.Email,
|
||||
Token: token.AccessToken,
|
||||
Avatar: *user.AvatarURL,
|
||||
Login: user.GetLogin(),
|
||||
Email: email.GetEmail(),
|
||||
Token: token.AccessToken,
|
||||
Avatar: user.GetAvatarURL(),
|
||||
ForgeRemoteID: model.ForgeRemoteID(fmt.Sprint(user.GetID())),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -133,11 +133,12 @@ func (g *GitLab) Login(ctx context.Context, res http.ResponseWriter, req *http.R
|
||||
}
|
||||
|
||||
user := &model.User{
|
||||
Login: login.Username,
|
||||
Email: login.Email,
|
||||
Avatar: login.AvatarURL,
|
||||
Token: token.AccessToken,
|
||||
Secret: token.RefreshToken,
|
||||
Login: login.Username,
|
||||
Email: login.Email,
|
||||
Avatar: login.AvatarURL,
|
||||
ForgeRemoteID: model.ForgeRemoteID(fmt.Sprint(login.ID)),
|
||||
Token: token.AccessToken,
|
||||
Secret: token.RefreshToken,
|
||||
}
|
||||
if !strings.HasPrefix(user.Avatar, "http") {
|
||||
user.Avatar = g.URL + "/" + login.AvatarURL
|
||||
|
@ -18,6 +18,7 @@ package gogs
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@ -118,10 +119,11 @@ func (c *client) Login(_ context.Context, res http.ResponseWriter, req *http.Req
|
||||
}
|
||||
|
||||
return &model.User{
|
||||
Token: accessToken,
|
||||
Login: account.UserName,
|
||||
Email: account.Email,
|
||||
Avatar: expandAvatar(c.URL, account.AvatarUrl),
|
||||
Token: accessToken,
|
||||
Login: account.UserName,
|
||||
Email: account.Email,
|
||||
Avatar: expandAvatar(c.URL, account.AvatarUrl),
|
||||
ForgeRemoteID: model.ForgeRemoteID(fmt.Sprint(account.ID)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.23.1. DO NOT EDIT.
|
||||
// Code generated by mockery v2.26.1. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
|
@ -34,6 +34,8 @@ type User struct {
|
||||
// required: true
|
||||
ID int64 `json:"id" xorm:"pk autoincr 'user_id'"`
|
||||
|
||||
ForgeRemoteID ForgeRemoteID `json:"-" xorm:"forge_remote_id"`
|
||||
|
||||
// Login is the username for this user.
|
||||
//
|
||||
// required: true
|
||||
|
@ -16,6 +16,7 @@ package datastore
|
||||
|
||||
import (
|
||||
"github.com/woodpecker-ci/woodpecker/server/model"
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
func (s storage) GetUser(id int64) (*model.User, error) {
|
||||
@ -23,9 +24,23 @@ func (s storage) GetUser(id int64) (*model.User, error) {
|
||||
return user, wrapGet(s.engine.ID(id).Get(user))
|
||||
}
|
||||
|
||||
func (s storage) GetUserLogin(login string) (*model.User, error) {
|
||||
func (s storage) GetUserRemoteID(remoteID model.ForgeRemoteID, login string) (*model.User, error) {
|
||||
sess := s.engine.NewSession()
|
||||
user := new(model.User)
|
||||
return user, wrapGet(s.engine.Where("user_login=?", login).Get(user))
|
||||
err := wrapGet(sess.Where("forge_remote_id = ?", remoteID).Get(user))
|
||||
if err != nil {
|
||||
user, err = s.getUserLogin(sess, login)
|
||||
}
|
||||
return user, err
|
||||
}
|
||||
|
||||
func (s storage) GetUserLogin(login string) (*model.User, error) {
|
||||
return s.getUserLogin(s.engine.NewSession(), login)
|
||||
}
|
||||
|
||||
func (s storage) getUserLogin(sess *xorm.Session, login string) (*model.User, error) {
|
||||
user := new(model.User)
|
||||
return user, wrapGet(sess.Where("user_login=?", login).Get(user))
|
||||
}
|
||||
|
||||
func (s storage) GetUserList(p *model.ListOptions) ([]*model.User, error) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.23.1. DO NOT EDIT.
|
||||
// Code generated by mockery v2.26.1. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
@ -1079,6 +1079,32 @@ func (_m *Store) GetUserLogin(_a0 string) (*model.User, error) {
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetUserRemoteID provides a mock function with given fields: _a0, _a1
|
||||
func (_m *Store) GetUserRemoteID(_a0 model.ForgeRemoteID, _a1 string) (*model.User, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
var r0 *model.User
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(model.ForgeRemoteID, string) (*model.User, error)); ok {
|
||||
return rf(_a0, _a1)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(model.ForgeRemoteID, string) *model.User); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*model.User)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(model.ForgeRemoteID, string) error); ok {
|
||||
r1 = rf(_a0, _a1)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GlobalSecretFind provides a mock function with given fields: _a0
|
||||
func (_m *Store) GlobalSecretFind(_a0 string) (*model.Secret, error) {
|
||||
ret := _m.Called(_a0)
|
||||
|
@ -29,6 +29,8 @@ type Store interface {
|
||||
// Users
|
||||
// GetUser gets a user by unique ID.
|
||||
GetUser(int64) (*model.User, error)
|
||||
// GetUserRemoteID gets a user by remote ID with fallback to login name.
|
||||
GetUserRemoteID(model.ForgeRemoteID, string) (*model.User, error)
|
||||
// GetUserLogin gets a user by unique Login name.
|
||||
GetUserLogin(string) (*model.User, error)
|
||||
// GetUserList gets a list of all users in the system.
|
||||
|
Loading…
x
Reference in New Issue
Block a user