mirror of
https://github.com/kubevela/kubevela.git
synced 2026-08-27 16:17:34 +00:00
Feat: support to init the roles of the user which login by dex
Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
This commit is contained in:
@@ -32,10 +32,16 @@ const (
|
||||
// SystemInfo systemInfo model
|
||||
type SystemInfo struct {
|
||||
BaseModel
|
||||
InstallID string `json:"installID"`
|
||||
EnableCollection bool `json:"enableCollection"`
|
||||
LoginType string `json:"loginType"`
|
||||
StatisticInfo StatisticInfo `json:"statisticInfo,omitempty"`
|
||||
InstallID string `json:"installID"`
|
||||
EnableCollection bool `json:"enableCollection"`
|
||||
StatisticInfo StatisticInfo `json:"statisticInfo,omitempty"`
|
||||
LoginType string `json:"loginType"`
|
||||
DexUserDefaultProjects []ProjectRef `json:"projects"`
|
||||
}
|
||||
|
||||
type ProjectRef struct {
|
||||
Name string `json:"name"`
|
||||
Roles []string `json:"roles"`
|
||||
}
|
||||
|
||||
// UpdateDexConfig update dex config
|
||||
|
||||
@@ -48,6 +48,7 @@ type User struct {
|
||||
LastLoginTime time.Time `json:"lastLoginTime,omitempty"`
|
||||
// UserRoles binding the platform level roles
|
||||
UserRoles []string `json:"userRoles"`
|
||||
DexSub string `json:"dexSub,omitempty"`
|
||||
}
|
||||
|
||||
// TableName return custom table name
|
||||
@@ -74,6 +75,9 @@ func (u *User) Index() map[string]string {
|
||||
if u.Email != "" {
|
||||
index["email"] = u.Email
|
||||
}
|
||||
if u.DexSub != "" {
|
||||
index["dexSub"] = u.DexSub
|
||||
}
|
||||
return index
|
||||
}
|
||||
|
||||
|
||||
@@ -68,10 +68,12 @@ type AuthenticationService interface {
|
||||
}
|
||||
|
||||
type authenticationServiceImpl struct {
|
||||
SysService SystemInfoService `inject:""`
|
||||
UserService UserService `inject:""`
|
||||
Store datastore.DataStore `inject:"datastore"`
|
||||
KubeClient client.Client `inject:"kubeClient"`
|
||||
SysService SystemInfoService `inject:""`
|
||||
UserService UserService `inject:""`
|
||||
ProjectService ProjectService `inject:""`
|
||||
SystemInfoService SystemInfoService `inject:""`
|
||||
Store datastore.DataStore `inject:"datastore"`
|
||||
KubeClient client.Client `inject:"kubeClient"`
|
||||
}
|
||||
|
||||
// NewAuthenticationService new authentication service
|
||||
@@ -84,8 +86,10 @@ type authHandler interface {
|
||||
}
|
||||
|
||||
type dexHandlerImpl struct {
|
||||
idToken *oidc.IDToken
|
||||
Store datastore.DataStore
|
||||
idToken *oidc.IDToken
|
||||
Store datastore.DataStore
|
||||
projectService ProjectService
|
||||
systemInfoService SystemInfoService
|
||||
}
|
||||
|
||||
type localHandlerImpl struct {
|
||||
@@ -124,8 +128,9 @@ func (a *authenticationServiceImpl) newDexHandler(ctx context.Context, req apisv
|
||||
return nil, err
|
||||
}
|
||||
return &dexHandlerImpl{
|
||||
idToken: idToken,
|
||||
Store: a.Store,
|
||||
idToken: idToken,
|
||||
Store: a.Store,
|
||||
projectService: a.ProjectService,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -433,31 +438,66 @@ func (a *authenticationServiceImpl) GetLoginType(ctx context.Context) (*apisv1.G
|
||||
func (d *dexHandlerImpl) login(ctx context.Context) (*apisv1.UserBase, error) {
|
||||
var claims struct {
|
||||
Email string `json:"email"`
|
||||
Name string `json:"name"`
|
||||
// Name End-User's full name in displayable form including all name parts, possibly including titles and suffixes, ordered according to the End-User's locale and preferences.
|
||||
Name string `json:"name"`
|
||||
// Subject - Identifier for the End-User at the Issuer.
|
||||
Sub string `json:"sub"`
|
||||
}
|
||||
if err := d.idToken.Claims(&claims); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
user := &model.User{Email: claims.Email}
|
||||
userBase := &apisv1.UserBase{Email: claims.Email, Name: claims.Name}
|
||||
users, err := d.Store.List(ctx, user, &datastore.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var users []datastore.Entity
|
||||
var err error
|
||||
if claims.Email != "" {
|
||||
user := &model.User{Email: claims.Email}
|
||||
users, err = d.Store.List(ctx, user, &datastore.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if len(users) == 0 && claims.Sub != "" {
|
||||
// Support query the user by the subject
|
||||
user := &model.User{DexSub: claims.Sub}
|
||||
users, err = d.Store.List(ctx, user, &datastore.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
var userBase *apisv1.UserBase
|
||||
if len(users) > 0 {
|
||||
u := users[0].(*model.User)
|
||||
u.LastLoginTime = time.Now()
|
||||
if err := d.Store.Put(ctx, u); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
userBase.Name = u.Name
|
||||
} else if err := d.Store.Add(ctx, &model.User{
|
||||
Email: claims.Email,
|
||||
Name: claims.Name,
|
||||
LastLoginTime: time.Now(),
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
userBase = convertUserBase(u)
|
||||
} else {
|
||||
user := &model.User{
|
||||
Email: claims.Email,
|
||||
Name: claims.Sub,
|
||||
DexSub: claims.Sub,
|
||||
Alias: claims.Name,
|
||||
LastLoginTime: time.Now(),
|
||||
}
|
||||
if err := d.Store.Add(ctx, user); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
systemInfo, err := d.systemInfoService.GetSystemInfo(ctx)
|
||||
if err != nil {
|
||||
log.Logger.Errorf("failed to get the system info %s", err.Error())
|
||||
}
|
||||
if systemInfo != nil {
|
||||
for _, project := range systemInfo.DexUserDefaultProjects {
|
||||
_, err := d.projectService.AddProjectUser(ctx, project.Name, apisv1.AddProjectUserRequest{
|
||||
UserName: claims.Sub,
|
||||
UserRoles: project.Roles,
|
||||
})
|
||||
if err != nil {
|
||||
log.Logger.Errorf("failed to add a user to project %s", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
userBase = convertUserBase(user)
|
||||
}
|
||||
|
||||
return userBase, nil
|
||||
|
||||
@@ -45,10 +45,11 @@ import (
|
||||
|
||||
var _ = Describe("Test authentication service functions", func() {
|
||||
var (
|
||||
authService *authenticationServiceImpl
|
||||
userService *userServiceImpl
|
||||
sysService *systemInfoServiceImpl
|
||||
ds datastore.DataStore
|
||||
authService *authenticationServiceImpl
|
||||
userService *userServiceImpl
|
||||
sysService *systemInfoServiceImpl
|
||||
projectService ProjectService
|
||||
ds datastore.DataStore
|
||||
)
|
||||
|
||||
BeforeEach(func() {
|
||||
@@ -59,42 +60,86 @@ var _ = Describe("Test authentication service functions", func() {
|
||||
authService = &authenticationServiceImpl{KubeClient: k8sClient, Store: ds}
|
||||
sysService = &systemInfoServiceImpl{Store: ds, KubeClient: k8sClient}
|
||||
userService = &userServiceImpl{Store: ds, SysService: sysService}
|
||||
projectService = NewTestProjectService(ds, k8sClient)
|
||||
})
|
||||
It("Test Dex login", func() {
|
||||
testIDToken := &oidc.IDToken{}
|
||||
patch := ApplyMethod(reflect.TypeOf(testIDToken), "Claims", func(_ *oidc.IDToken, v interface{}) error {
|
||||
return json.Unmarshal([]byte(`{"email":"test@test.com","name":"test"}`), v)
|
||||
return json.Unmarshal([]byte(`{"email":"test@test.com", "name":"show name", "sub": "testuser"}`), v)
|
||||
})
|
||||
defer patch.Reset()
|
||||
|
||||
err := sysService.Init(context.TODO())
|
||||
Expect(err).Should(BeNil())
|
||||
err = userService.Init(context.TODO())
|
||||
Expect(err).Should(BeNil())
|
||||
err = projectService.Init(context.TODO())
|
||||
Expect(err).Should(BeNil())
|
||||
|
||||
_, err = sysService.UpdateSystemInfo(context.TODO(), apisv1.SystemInfoRequest{
|
||||
LoginType: "local",
|
||||
DexUserDefaultProjects: []model.ProjectRef{{
|
||||
Name: "default",
|
||||
Roles: []string{"app-developer"},
|
||||
}},
|
||||
})
|
||||
Expect(err).Should(BeNil())
|
||||
|
||||
dexHandler := dexHandlerImpl{
|
||||
idToken: testIDToken,
|
||||
Store: ds,
|
||||
idToken: testIDToken,
|
||||
Store: ds,
|
||||
projectService: projectService,
|
||||
systemInfoService: sysService,
|
||||
}
|
||||
resp, err := dexHandler.login(context.Background())
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(resp.Email).Should(Equal("test@test.com"))
|
||||
Expect(resp.Name).Should(Equal("test"))
|
||||
Expect(resp.Name).Should(Equal("testuser"))
|
||||
Expect(resp.Alias).Should(Equal("show name"))
|
||||
|
||||
projects, err := projectService.ListUserProjects(context.TODO(), "testuser")
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(len(projects)).Should(Equal(1))
|
||||
|
||||
user := &model.User{
|
||||
Name: "test",
|
||||
Name: "testuser",
|
||||
}
|
||||
err = ds.Get(context.Background(), user)
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(user.Email).Should(Equal("test@test.com"))
|
||||
|
||||
existUser := &model.User{
|
||||
Name: "test",
|
||||
Name: "testuser",
|
||||
}
|
||||
err = ds.Delete(context.Background(), existUser)
|
||||
Expect(err).Should(BeNil())
|
||||
existUser.Name = "exist-user"
|
||||
existUser.Email = "test@test.com"
|
||||
|
||||
existUser = &model.User{
|
||||
Name: "exist-user",
|
||||
Email: "test@test.com",
|
||||
}
|
||||
err = ds.Add(context.Background(), existUser)
|
||||
Expect(err).Should(BeNil())
|
||||
resp, err = dexHandler.login(context.Background())
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(resp.Email).Should(Equal("test@test.com"))
|
||||
Expect(resp.Name).Should(Equal("exist-user"))
|
||||
|
||||
err = ds.Delete(context.Background(), existUser)
|
||||
Expect(err).Should(BeNil())
|
||||
|
||||
existUser = &model.User{
|
||||
Name: "zhangsan",
|
||||
Email: "test2@test.com",
|
||||
DexSub: "testuser",
|
||||
}
|
||||
err = ds.Add(context.Background(), existUser)
|
||||
Expect(err).Should(BeNil())
|
||||
resp, err = dexHandler.login(context.Background())
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(resp.Email).Should(Equal("test2@test.com"))
|
||||
Expect(resp.Name).Should(Equal("zhangsan"))
|
||||
|
||||
})
|
||||
|
||||
It("Test local login", func() {
|
||||
|
||||
@@ -113,7 +113,8 @@ func (u systemInfoServiceImpl) UpdateSystemInfo(ctx context.Context, sysInfo v1.
|
||||
CreateTime: info.CreateTime,
|
||||
UpdateTime: time.Now(),
|
||||
},
|
||||
StatisticInfo: info.StatisticInfo,
|
||||
StatisticInfo: info.StatisticInfo,
|
||||
DexUserDefaultProjects: sysInfo.DexUserDefaultProjects,
|
||||
}
|
||||
|
||||
if sysInfo.LoginType == model.LoginTypeDex {
|
||||
@@ -166,9 +167,10 @@ func (u systemInfoServiceImpl) Init(ctx context.Context) error {
|
||||
|
||||
func convertInfoToBase(info *model.SystemInfo) v1.SystemInfo {
|
||||
return v1.SystemInfo{
|
||||
PlatformID: info.InstallID,
|
||||
EnableCollection: info.EnableCollection,
|
||||
LoginType: info.LoginType,
|
||||
InstallTime: info.CreateTime,
|
||||
PlatformID: info.InstallID,
|
||||
EnableCollection: info.EnableCollection,
|
||||
LoginType: info.LoginType,
|
||||
InstallTime: info.CreateTime,
|
||||
DexUserDefaultProjects: info.DexUserDefaultProjects,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1194,10 +1194,11 @@ type SystemInfoResponse struct {
|
||||
|
||||
// SystemInfo system info
|
||||
type SystemInfo struct {
|
||||
PlatformID string `json:"platformID"`
|
||||
EnableCollection bool `json:"enableCollection"`
|
||||
LoginType string `json:"loginType"`
|
||||
InstallTime time.Time `json:"installTime,omitempty"`
|
||||
PlatformID string `json:"platformID"`
|
||||
EnableCollection bool `json:"enableCollection"`
|
||||
LoginType string `json:"loginType" validate:"oneof=dex local"`
|
||||
InstallTime time.Time `json:"installTime,omitempty"`
|
||||
DexUserDefaultProjects []model.ProjectRef `json:"dexUserDefaultProjects,omitempty"`
|
||||
}
|
||||
|
||||
// StatisticInfo generated by cronJob running in backend
|
||||
@@ -1214,9 +1215,10 @@ type StatisticInfo struct {
|
||||
|
||||
// SystemInfoRequest request by update SystemInfo
|
||||
type SystemInfoRequest struct {
|
||||
EnableCollection bool `json:"enableCollection"`
|
||||
LoginType string `json:"loginType"`
|
||||
VelaAddress string `json:"velaAddress,omitempty"`
|
||||
EnableCollection bool `json:"enableCollection"`
|
||||
LoginType string `json:"loginType"`
|
||||
VelaAddress string `json:"velaAddress,omitempty"`
|
||||
DexUserDefaultProjects []model.ProjectRef `json:"dexUserDefaultProjects,omitempty"`
|
||||
}
|
||||
|
||||
// SystemVersion contains KubeVela version
|
||||
|
||||
Reference in New Issue
Block a user