Merge pull request #2649 from ywk253100/170627_service_account

Implement GetByMember function in PMS project manager
This commit is contained in:
Wenkai Yin 2017-06-28 15:25:21 +08:00 committed by GitHub
commit ab65bca2fe
6 changed files with 78 additions and 24 deletions

View File

@ -21,8 +21,6 @@ import (
"io/ioutil"
"net/http"
"strings"
"github.com/vmware/harbor/src/ui/config"
)
const (
@ -92,9 +90,31 @@ func (a *AuthContext) HasAllPerm(project string) bool {
return false
}
// GetByToken ...
func GetByToken(token string) (*AuthContext, error) {
req, err := http.NewRequest(http.MethodGet, buildCtxURL(), nil)
// GetMyProjects returns all projects which the user is a member of
func (a *AuthContext) GetMyProjects() ([]string, error) {
existence := map[string]string{}
projects := []string{}
for _, list := range a.Projects {
for _, p := range list {
if len(existence[p]) > 0 {
continue
}
existence[p] = p
projects = append(projects, p)
}
}
return projects, nil
}
// GetByToken gets the user's auth context, if the username is not provided
// get the default auth context of the token
func GetByToken(url, token string, username ...string) (*AuthContext, error) {
principalID := ""
if len(username) > 0 {
principalID = username[0]
}
req, err := http.NewRequest(http.MethodGet, buildCtxURL(url, principalID), nil)
if err != nil {
return nil, err
}
@ -119,7 +139,7 @@ func GetByToken(token string) (*AuthContext, error) {
}
// Login ...
func Login(username, password string) (string, *AuthContext, error) {
func Login(url, username, password string) (string, *AuthContext, error) {
data, err := json.Marshal(&struct {
Username string `json:"username"`
Password string `json:"password"`
@ -131,7 +151,7 @@ func Login(username, password string) (string, *AuthContext, error) {
return "", nil, err
}
req, err := http.NewRequest(http.MethodPost, buildLoginURL(), bytes.NewBuffer(data))
req, err := http.NewRequest(http.MethodPost, buildLoginURL(url), bytes.NewBuffer(data))
if err != nil {
return "", nil, err
}
@ -166,10 +186,14 @@ func send(req *http.Request) (int, http.Header, []byte, error) {
return resp.StatusCode, resp.Header, data, nil
}
func buildCtxURL() string {
return strings.TrimRight(config.AdmiralEndpoint(), "/") + "/sso/auth-context"
func buildCtxURL(url, principalID string) string {
url = strings.TrimRight(url, "/") + "/sso/auth-context"
if len(principalID) > 0 {
url += "/" + principalID
}
return url
}
func buildLoginURL() string {
return strings.TrimRight(config.AdmiralEndpoint(), "/") + "/sso/login"
func buildLoginURL(url string) string {
return strings.TrimRight(url, "/") + "/sso/login"
}

View File

@ -24,8 +24,8 @@ type Context interface {
IsSysAdmin() bool
// HasReadPerm returns whether the user has read permission to the project
HasReadPerm(projectIDOrName interface{}) bool
// HasWritePerm returns whether the user has write permission to the project
// HasWritePerm returns whether the user has write permission to the project
HasWritePerm(projectIDOrName interface{}) bool
// HasAllPerm returns whether the user has all permissions to the project
// HasAllPerm returns whether the user has all permissions to the project
HasAllPerm(projectIDOrName interface{}) bool
}

View File

@ -131,7 +131,7 @@ func (b *basicAuthReqCtxModifier) Modify(ctx *beegoctx.Context) bool {
if config.WithAdmiral() {
// integration with admiral
token, authCtx, err := authcontext.Login(username, password)
token, authCtx, err := authcontext.Login(config.AdmiralEndpoint(), username, password)
if err != nil {
log.Errorf("failed to authenticate %s: %v", username, err)
return false
@ -204,7 +204,7 @@ func (t *tokenReqCtxModifier) Modify(ctx *beegoctx.Context) bool {
log.Debug("got token from request")
authContext, err := authcontext.GetByToken(token)
authContext, err := authcontext.GetByToken(config.AdmiralEndpoint(), token)
if err != nil {
log.Errorf("failed to get auth context: %v", err)
return false

View File

@ -115,6 +115,10 @@ func (p *ProjectManager) GetPublic() ([]*models.Project, error) {
// GetByMember returns all projects which the user is a member of
func (p *ProjectManager) GetByMember(username string) (
[]*models.Project, error) {
if len(username) == 0 {
return []*models.Project{}, nil
}
return p.GetAll(&models.ProjectQueryParam{
Member: &models.MemberQuery{
Name: username,

View File

@ -153,7 +153,13 @@ func TestGetPublic(t *testing.T) {
func TestGetByMember(t *testing.T) {
pm := &ProjectManager{}
projects, err := pm.GetByMember("admin")
// empty username
projects, err := pm.GetByMember("")
assert.Nil(t, err)
assert.Equal(t, 0, len(projects))
//non-empty username
projects, err = pm.GetByMember("admin")
assert.Nil(t, err)
assert.NotEqual(t, 0, len(projects))
}

View File

@ -28,6 +28,7 @@ import (
"github.com/vmware/harbor/src/common"
"github.com/vmware/harbor/src/common/models"
"github.com/vmware/harbor/src/common/security/authcontext"
er "github.com/vmware/harbor/src/common/utils/error"
"github.com/vmware/harbor/src/common/utils/log"
)
@ -230,8 +231,11 @@ func (p *ProjectManager) Exist(projectIDOrName interface{}) (bool, error) {
return project != nil, nil
}
// GetRoles ...
// TODO empty this method after implementing security context with auth context
// GetRoles gets roles that the user has to the project
// This method is used in GET /projects API.
// Jobservice calls GET /projects API to get information of source
// project when trying to replicate the project. There is no auth
// context in this use case, so the method is needed.
func (p *ProjectManager) GetRoles(username string, projectIDOrName interface{}) ([]int, error) {
if len(username) == 0 || projectIDOrName == nil {
return nil, nil
@ -303,8 +307,26 @@ func (p *ProjectManager) GetPublic() ([]*models.Project, error) {
// GetByMember ...
func (p *ProjectManager) GetByMember(username string) ([]*models.Project, error) {
// TODO add implement
return nil, nil
projects := []*models.Project{}
ctx, err := authcontext.GetByToken(p.endpoint, p.token, username)
if err != nil {
return projects, err
}
names, err := ctx.GetMyProjects()
if err != nil {
return projects, err
}
for _, name := range names {
project, err := p.Get(name)
if err != nil {
return projects, err
}
projects = append(projects, project)
}
return projects, nil
}
// Create ...
@ -396,11 +418,9 @@ func (p *ProjectManager) GetTotal(query *models.ProjectQueryParam, base ...*mode
return int64(len(projects)), err
}
// GetHasReadPerm returns all projects that user has read perm to
// TODO maybe can be removed as search isn't implemented in integration mode
// GetHasReadPerm ...
func (p *ProjectManager) GetHasReadPerm(username ...string) ([]*models.Project, error) {
// TODO add implement
return nil, nil
return nil, errors.New("GetHasReadPerm is unsupported")
}
func (p *ProjectManager) send(method, path string, body io.Reader) ([]byte, error) {