mirror of
https://github.com/goharbor/harbor
synced 2025-04-10 14:07:08 +00:00
add comments to pass golint
This commit is contained in:
parent
415dc84560
commit
4a24d642b7
|
@ -24,18 +24,22 @@ import (
|
|||
"github.com/astaxie/beego"
|
||||
)
|
||||
|
||||
// BaseAPI wraps common methods for controllers to host API
|
||||
type BaseAPI struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
// Render returns nil as it won't render template
|
||||
func (b *BaseAPI) Render() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// RenderError provides shortcut to render http error
|
||||
func (b *BaseAPI) RenderError(code int, text string) {
|
||||
http.Error(b.Ctx.ResponseWriter, text, code)
|
||||
}
|
||||
|
||||
// DecodeJSONReq decodes a json request
|
||||
func (b *BaseAPI) DecodeJSONReq(v interface{}) {
|
||||
err := json.Unmarshal(b.Ctx.Input.CopyBody(1<<32), v)
|
||||
if err != nil {
|
||||
|
@ -44,6 +48,7 @@ func (b *BaseAPI) DecodeJSONReq(v interface{}) {
|
|||
}
|
||||
}
|
||||
|
||||
// ValidateUser checks if the request triggered by a valid user
|
||||
func (b *BaseAPI) ValidateUser() int {
|
||||
|
||||
sessionUserID := b.GetSession("userId")
|
||||
|
|
|
@ -24,6 +24,7 @@ import (
|
|||
"github.com/astaxie/beego"
|
||||
)
|
||||
|
||||
// ProjectMemberAPI handles request to /api/projects/{}/members/{}
|
||||
type ProjectMemberAPI struct {
|
||||
BaseAPI
|
||||
memberID int
|
||||
|
@ -37,6 +38,7 @@ type memberReq struct {
|
|||
Roles []int `json:"roles"`
|
||||
}
|
||||
|
||||
// Prepare validates the URL and parms
|
||||
func (pma *ProjectMemberAPI) Prepare() {
|
||||
pid, err := strconv.ParseInt(pma.Ctx.Input.Param(":pid"), 10, 64)
|
||||
if err != nil {
|
||||
|
@ -71,9 +73,10 @@ func (pma *ProjectMemberAPI) Prepare() {
|
|||
}
|
||||
}
|
||||
|
||||
// Get ...
|
||||
func (pma *ProjectMemberAPI) Get() {
|
||||
pid := pma.project.ProjectID
|
||||
if !CheckProjectPermission(pma.currentUserID, pid) {
|
||||
if !checkProjectPermission(pma.currentUserID, pid) {
|
||||
beego.Warning("Current user, user id :", pma.currentUserID, "does not have permission for project, id:", pid)
|
||||
pma.RenderError(http.StatusForbidden, "")
|
||||
return
|
||||
|
@ -109,6 +112,7 @@ func (pma *ProjectMemberAPI) Get() {
|
|||
pma.ServeJSON()
|
||||
}
|
||||
|
||||
// Post ...
|
||||
func (pma *ProjectMemberAPI) Post() {
|
||||
pid := pma.project.ProjectID
|
||||
userQuery := models.User{UserID: pma.currentUserID, RoleID: models.PROJECTADMIN}
|
||||
|
@ -125,7 +129,7 @@ func (pma *ProjectMemberAPI) Post() {
|
|||
var req memberReq
|
||||
pma.DecodeJSONReq(&req)
|
||||
username := req.Username
|
||||
userID := CheckUserExists(username)
|
||||
userID := checkUserExists(username)
|
||||
if userID <= 0 {
|
||||
beego.Warning("User does not exist, user name:", username)
|
||||
pma.RenderError(http.StatusNotFound, "User does not exist")
|
||||
|
@ -152,6 +156,7 @@ func (pma *ProjectMemberAPI) Post() {
|
|||
}
|
||||
}
|
||||
|
||||
// Put ...
|
||||
func (pma *ProjectMemberAPI) Put() {
|
||||
pid := pma.project.ProjectID
|
||||
mid := pma.memberID
|
||||
|
@ -193,6 +198,7 @@ func (pma *ProjectMemberAPI) Put() {
|
|||
}
|
||||
}
|
||||
|
||||
// Delete ...
|
||||
func (pma *ProjectMemberAPI) Delete() {
|
||||
pid := pma.project.ProjectID
|
||||
mid := pma.memberID
|
||||
|
|
|
@ -28,6 +28,7 @@ import (
|
|||
"github.com/astaxie/beego"
|
||||
)
|
||||
|
||||
// ProjectAPI handles request to /api/projects/{} /api/projects/{}/logs
|
||||
type ProjectAPI struct {
|
||||
BaseAPI
|
||||
userID int
|
||||
|
@ -41,6 +42,7 @@ type projectReq struct {
|
|||
|
||||
const projectNameMaxLen int = 30
|
||||
|
||||
// Prepare validates the URL and the user
|
||||
func (p *ProjectAPI) Prepare() {
|
||||
p.userID = p.ValidateUser()
|
||||
idStr := p.Ctx.Input.Param(":id")
|
||||
|
@ -62,6 +64,7 @@ func (p *ProjectAPI) Prepare() {
|
|||
}
|
||||
}
|
||||
|
||||
// Post ...
|
||||
func (p *ProjectAPI) Post() {
|
||||
var req projectReq
|
||||
var public int
|
||||
|
@ -92,6 +95,7 @@ func (p *ProjectAPI) Post() {
|
|||
}
|
||||
}
|
||||
|
||||
// Head ...
|
||||
func (p *ProjectAPI) Head() {
|
||||
projectName := p.GetString("project_name")
|
||||
result, err := dao.ProjectExists(projectName)
|
||||
|
@ -106,6 +110,7 @@ func (p *ProjectAPI) Head() {
|
|||
}
|
||||
}
|
||||
|
||||
// Get ...
|
||||
func (p *ProjectAPI) Get() {
|
||||
queryProject := models.Project{UserID: p.userID}
|
||||
projectName := p.GetString("project_name")
|
||||
|
@ -129,6 +134,7 @@ func (p *ProjectAPI) Get() {
|
|||
p.ServeJSON()
|
||||
}
|
||||
|
||||
// Put ...
|
||||
func (p *ProjectAPI) Put() {
|
||||
var req projectReq
|
||||
var public int
|
||||
|
@ -156,6 +162,7 @@ func (p *ProjectAPI) Put() {
|
|||
}
|
||||
}
|
||||
|
||||
// FilterAccessLog handles GET to /api/projects/{}/logs
|
||||
func (p *ProjectAPI) FilterAccessLog() {
|
||||
|
||||
var filter models.AccessLog
|
||||
|
|
|
@ -28,15 +28,17 @@ import (
|
|||
"github.com/astaxie/beego"
|
||||
)
|
||||
|
||||
//For repostiories, we won't check the session in this API due to search functionality, querying manifest will be contorlled by
|
||||
//the security of registry
|
||||
|
||||
// RepositoryAPI handles request to /api/repositories /api/repositories/tags /api/repositories/manifests, the parm has to be put
|
||||
// in the query string as the web framework can not parse the URL if it contains veriadic sectors.
|
||||
// For repostiories, we won't check the session in this API due to search functionality, querying manifest will be contorlled by
|
||||
// the security of registry
|
||||
type RepositoryAPI struct {
|
||||
BaseAPI
|
||||
userID int
|
||||
username string
|
||||
}
|
||||
|
||||
// Prepare will set a non existent user ID in case the request tries to view repositories under a project he doesn't has permission.
|
||||
func (ra *RepositoryAPI) Prepare() {
|
||||
userID, ok := ra.GetSession("userId").(int)
|
||||
if !ok {
|
||||
|
@ -53,6 +55,7 @@ func (ra *RepositoryAPI) Prepare() {
|
|||
}
|
||||
}
|
||||
|
||||
// Get ...
|
||||
func (ra *RepositoryAPI) Get() {
|
||||
projectID, err0 := ra.GetInt64("project_id")
|
||||
if err0 != nil {
|
||||
|
@ -70,7 +73,7 @@ func (ra *RepositoryAPI) Get() {
|
|||
ra.RenderError(http.StatusNotFound, "")
|
||||
return
|
||||
}
|
||||
if p.Public == 0 && !CheckProjectPermission(ra.userID, projectID) {
|
||||
if p.Public == 0 && !checkProjectPermission(ra.userID, projectID) {
|
||||
ra.RenderError(http.StatusForbidden, "")
|
||||
return
|
||||
}
|
||||
|
@ -102,23 +105,24 @@ func (ra *RepositoryAPI) Get() {
|
|||
ra.ServeJSON()
|
||||
}
|
||||
|
||||
type Tag struct {
|
||||
type tag struct {
|
||||
Name string `json:"name"`
|
||||
Tags []string `json:"tags"`
|
||||
}
|
||||
|
||||
type HistroyItem struct {
|
||||
type histroyItem struct {
|
||||
V1Compatibility string `json:"v1Compatibility"`
|
||||
}
|
||||
|
||||
type Manifest struct {
|
||||
type manifest struct {
|
||||
Name string `json:"name"`
|
||||
Tag string `json:"tag"`
|
||||
Architecture string `json:"architecture"`
|
||||
SchemaVersion int `json:"schemaVersion"`
|
||||
History []HistroyItem `json:"history"`
|
||||
History []histroyItem `json:"history"`
|
||||
}
|
||||
|
||||
// GetTags handles GET /api/repositories/tags
|
||||
func (ra *RepositoryAPI) GetTags() {
|
||||
|
||||
var tags []string
|
||||
|
@ -129,7 +133,7 @@ func (ra *RepositoryAPI) GetTags() {
|
|||
beego.Error("Failed to get repo tags, repo name:", repoName, ", error: ", err)
|
||||
ra.RenderError(http.StatusInternalServerError, "Failed to get repo tags")
|
||||
} else {
|
||||
t := Tag{}
|
||||
t := tag{}
|
||||
json.Unmarshal(result, &t)
|
||||
tags = t.Tags
|
||||
}
|
||||
|
@ -137,6 +141,7 @@ func (ra *RepositoryAPI) GetTags() {
|
|||
ra.ServeJSON()
|
||||
}
|
||||
|
||||
// GetManifests handles GET /api/repositories/manifests
|
||||
func (ra *RepositoryAPI) GetManifests() {
|
||||
repoName := ra.GetString("repo_name")
|
||||
tag := ra.GetString("tag")
|
||||
|
@ -149,7 +154,7 @@ func (ra *RepositoryAPI) GetManifests() {
|
|||
ra.RenderError(http.StatusInternalServerError, "Internal Server Error")
|
||||
return
|
||||
}
|
||||
mani := Manifest{}
|
||||
mani := manifest{}
|
||||
err = json.Unmarshal(result, &mani)
|
||||
if err != nil {
|
||||
beego.Error("Failed to decode json from response for manifests, repo name:", repoName, ", tag:", tag, ", error:", err)
|
||||
|
|
|
@ -27,15 +27,17 @@ import (
|
|||
"github.com/astaxie/beego"
|
||||
)
|
||||
|
||||
// SearchAPI handles requesst to /api/search
|
||||
type SearchAPI struct {
|
||||
BaseAPI
|
||||
}
|
||||
|
||||
type SearchResult struct {
|
||||
type searchResult struct {
|
||||
Project []map[string]interface{} `json:"project"`
|
||||
Repository []map[string]interface{} `json:"repository"`
|
||||
}
|
||||
|
||||
// Get ...
|
||||
func (n *SearchAPI) Get() {
|
||||
userID, ok := n.GetSession("userId").(int)
|
||||
if !ok {
|
||||
|
@ -71,7 +73,7 @@ func (n *SearchAPI) Get() {
|
|||
}
|
||||
sort.Strings(repositories)
|
||||
repositoryResult := filterRepositories(repositories, projects, keyword)
|
||||
result := &SearchResult{Project: projectResult, Repository: repositoryResult}
|
||||
result := &searchResult{Project: projectResult, Repository: repositoryResult}
|
||||
n.Data["json"] = result
|
||||
n.ServeJSON()
|
||||
}
|
||||
|
|
|
@ -24,12 +24,14 @@ import (
|
|||
"github.com/astaxie/beego"
|
||||
)
|
||||
|
||||
// UserAPI handles request to /api/users/{}
|
||||
type UserAPI struct {
|
||||
BaseAPI
|
||||
currentUserID int
|
||||
userID int
|
||||
}
|
||||
|
||||
// Prepare validates the URL and parms
|
||||
func (ua *UserAPI) Prepare() {
|
||||
|
||||
ua.currentUserID = ua.ValidateUser()
|
||||
|
@ -56,6 +58,7 @@ func (ua *UserAPI) Prepare() {
|
|||
}
|
||||
}
|
||||
|
||||
// Get ...
|
||||
func (ua *UserAPI) Get() {
|
||||
exist, err := dao.IsAdminRole(ua.currentUserID)
|
||||
if err != nil {
|
||||
|
@ -98,6 +101,7 @@ func (ua *UserAPI) Get() {
|
|||
ua.ServeJSON()
|
||||
}
|
||||
|
||||
// Put ...
|
||||
func (ua *UserAPI) Put() { //currently only for toggle admin, so no request body
|
||||
exist, err := dao.IsAdminRole(ua.currentUserID)
|
||||
if err != nil {
|
||||
|
@ -113,6 +117,7 @@ func (ua *UserAPI) Put() { //currently only for toggle admin, so no request body
|
|||
dao.ToggleUserAdminRole(userQuery)
|
||||
}
|
||||
|
||||
// Delete ...
|
||||
func (ua *UserAPI) Delete() {
|
||||
exist, err := dao.IsAdminRole(ua.currentUserID)
|
||||
if err != nil {
|
||||
|
|
|
@ -21,7 +21,7 @@ import (
|
|||
"github.com/astaxie/beego"
|
||||
)
|
||||
|
||||
func CheckProjectPermission(userID int, projectID int64) bool {
|
||||
func checkProjectPermission(userID int, projectID int64) bool {
|
||||
exist, err := dao.IsAdminRole(userID)
|
||||
if err != nil {
|
||||
beego.Error("Error occurred in IsAdminRole:", err)
|
||||
|
@ -38,7 +38,7 @@ func CheckProjectPermission(userID int, projectID int64) bool {
|
|||
return len(roleList) > 0
|
||||
}
|
||||
|
||||
func CheckUserExists(name string) int {
|
||||
func checkUserExists(name string) int {
|
||||
u, err := dao.GetUser(models.User{Username: name})
|
||||
if err != nil {
|
||||
beego.Error("Error occurred in GetUser:", err)
|
||||
|
|
|
@ -24,12 +24,16 @@ import (
|
|||
"github.com/astaxie/beego"
|
||||
)
|
||||
|
||||
// Authenticator provides interface to authenticate user credentials.
|
||||
type Authenticator interface {
|
||||
|
||||
// Authenticate ...
|
||||
Authenticate(m models.AuthModel) (*models.User, error)
|
||||
}
|
||||
|
||||
var registry = make(map[string]Authenticator)
|
||||
|
||||
// Register add different authenticators to registry map.
|
||||
func Register(name string, authenticator Authenticator) {
|
||||
if _, dup := registry[name]; dup {
|
||||
log.Printf("authenticator: %s has been registered", name)
|
||||
|
@ -38,6 +42,7 @@ func Register(name string, authenticator Authenticator) {
|
|||
registry[name] = authenticator
|
||||
}
|
||||
|
||||
// Login authenticates user credentials based on setting.
|
||||
func Login(m models.AuthModel) (*models.User, error) {
|
||||
|
||||
var authMode = os.Getenv("AUTH_MODE")
|
||||
|
|
|
@ -20,8 +20,10 @@ import (
|
|||
"github.com/vmware/harbor/models"
|
||||
)
|
||||
|
||||
// Auth implements Authenticator interface to authenticate user against DB.
|
||||
type Auth struct{}
|
||||
|
||||
// Authenticate calls dao to authenticate user.
|
||||
func (d *Auth) Authenticate(m models.AuthModel) (*models.User, error) {
|
||||
u, err := dao.LoginByDb(m)
|
||||
if err != nil {
|
||||
|
|
|
@ -29,10 +29,14 @@ import (
|
|||
"github.com/mqu/openldap"
|
||||
)
|
||||
|
||||
// Auth implements Authenticator interface to authenticate against LDAP
|
||||
type Auth struct{}
|
||||
|
||||
const metaChars = "&|!=~*<>()"
|
||||
|
||||
// Authenticate checks user's credential agains LDAP based on basedn template and LDAP URL,
|
||||
// if the check is successful a dummy record will be insert into DB, such that this user can
|
||||
// be associated to other entities in the system.
|
||||
func (l *Auth) Authenticate(m models.AuthModel) (*models.User, error) {
|
||||
|
||||
ldapURL := os.Getenv("LDAP_URL")
|
||||
|
|
|
@ -23,14 +23,17 @@ import (
|
|||
"github.com/beego/i18n"
|
||||
)
|
||||
|
||||
// CommonControler handles request from UI that doesn't expect a page, such as /login /logout ...
|
||||
type CommonController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
// Render returns nil.
|
||||
func (c *CommonController) Render() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// BaseController wraps common methods such as i18n support, forward, which can be leveraged by other UI render controllers.
|
||||
type BaseController struct {
|
||||
beego.Controller
|
||||
i18n.Locale
|
||||
|
@ -47,6 +50,7 @@ const (
|
|||
|
||||
var supportLanguages map[string]langType
|
||||
|
||||
// Prepare extracts the language information from request and populate data for rendering templates.
|
||||
func (b *BaseController) Prepare() {
|
||||
|
||||
var lang string
|
||||
|
@ -99,6 +103,7 @@ func (b *BaseController) Prepare() {
|
|||
b.Data["AuthMode"] = authMode
|
||||
}
|
||||
|
||||
// ForwardTo setup layout and template for content for a page.
|
||||
func (b *BaseController) ForwardTo(pageTitle string, pageName string) {
|
||||
b.Layout = "segment/base-layout.tpl"
|
||||
b.TplName = "segment/base-layout.tpl"
|
||||
|
|
|
@ -25,10 +25,13 @@ import (
|
|||
"github.com/astaxie/beego"
|
||||
)
|
||||
|
||||
// ItemDetailController handles requet to /registry/detail, which shows the detail of a project.
|
||||
type ItemDetailController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
// Get will check if user has permission to view a certain project, if not user will be redirected to signin or his homepage.
|
||||
// If the check is passed it renders the project detail page.
|
||||
func (idc *ItemDetailController) Get() {
|
||||
|
||||
projectID, _ := idc.GetInt64("project_id")
|
||||
|
|
|
@ -23,23 +23,28 @@ import (
|
|||
"github.com/astaxie/beego"
|
||||
)
|
||||
|
||||
// IndexController handles request to /
|
||||
type IndexController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
// Get renders the index page.
|
||||
func (c *IndexController) Get() {
|
||||
c.Data["Username"] = c.GetSession("username")
|
||||
c.ForwardTo("page_title_index", "index")
|
||||
}
|
||||
|
||||
// SignInController handles request to /signIn
|
||||
type SignInController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
// Get renders Sign In page.
|
||||
func (sic *SignInController) Get() {
|
||||
sic.ForwardTo("page_title_sign_in", "sign-in")
|
||||
}
|
||||
|
||||
// Login handles login request from UI.
|
||||
func (c *CommonController) Login() {
|
||||
principal := c.GetString("principal")
|
||||
password := c.GetString("password")
|
||||
|
@ -58,6 +63,7 @@ func (c *CommonController) Login() {
|
|||
c.SetSession("username", user.Username)
|
||||
}
|
||||
|
||||
// SwitchLanguage handles UI request to switch between different languages and re-render template based on language.
|
||||
func (c *CommonController) SwitchLanguage() {
|
||||
lang := c.GetString("lang")
|
||||
if lang == "en-US" || lang == "zh-CN" {
|
||||
|
@ -67,6 +73,7 @@ func (c *CommonController) SwitchLanguage() {
|
|||
c.Redirect(c.Ctx.Request.Header.Get("Referer"), http.StatusFound)
|
||||
}
|
||||
|
||||
// Logout handles UI request to logout.
|
||||
func (c *CommonController) Logout() {
|
||||
c.DestroySession()
|
||||
}
|
||||
|
|
|
@ -28,10 +28,12 @@ import (
|
|||
"github.com/astaxie/beego"
|
||||
)
|
||||
|
||||
// ChangePasswordController handles request to /changePassword
|
||||
type ChangePasswordController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
// Get renders the page for user to change password.
|
||||
func (cpc *ChangePasswordController) Get() {
|
||||
sessionUserID := cpc.GetSession("userId")
|
||||
if sessionUserID == nil {
|
||||
|
@ -42,6 +44,7 @@ func (cpc *ChangePasswordController) Get() {
|
|||
cpc.ForwardTo("page_title_change_password", "change-password")
|
||||
}
|
||||
|
||||
// UpdatePassword handles UI request to update user's password, it only works when the auth mode is db_auth.
|
||||
func (cc *CommonController) UpdatePassword() {
|
||||
|
||||
sessionUserID := cc.GetSession("userId")
|
||||
|
@ -82,20 +85,23 @@ func (cc *CommonController) UpdatePassword() {
|
|||
}
|
||||
}
|
||||
|
||||
// ForgotPasswordController handles request to /forgotPassword
|
||||
type ForgotPasswordController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
type MessageDetail struct {
|
||||
// Get Renders the page for user to input Email to reset password.
|
||||
func (fpc *ForgotPasswordController) Get() {
|
||||
fpc.ForwardTo("page_title_forgot_password", "forgot-password")
|
||||
}
|
||||
|
||||
type messageDetail struct {
|
||||
Hint string
|
||||
URL string
|
||||
UUID string
|
||||
}
|
||||
|
||||
func (fpc *ForgotPasswordController) Get() {
|
||||
fpc.ForwardTo("page_title_forgot_password", "forgot-password")
|
||||
}
|
||||
|
||||
// SendEmail verifies the Email address and contact SMTP server to send reset password Email.
|
||||
func (cc *CommonController) SendEmail() {
|
||||
|
||||
email := cc.GetString("email")
|
||||
|
@ -133,7 +139,7 @@ func (cc *CommonController) SendEmail() {
|
|||
beego.Error("Error occurred in GenerateRandomString:", err)
|
||||
cc.CustomAbort(http.StatusInternalServerError, "Internal error.")
|
||||
}
|
||||
err = messageTemplate.Execute(message, MessageDetail{
|
||||
err = messageTemplate.Execute(message, messageDetail{
|
||||
Hint: cc.Tr("reset_email_hint"),
|
||||
URL: harborURL,
|
||||
UUID: uuid,
|
||||
|
@ -170,10 +176,12 @@ func (cc *CommonController) SendEmail() {
|
|||
|
||||
}
|
||||
|
||||
// ResetPasswordController handles request to /resetPassword
|
||||
type ResetPasswordController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
// Get checks if reset_uuid in the reset link is valid and render the result page for user to reset password.
|
||||
func (rpc *ResetPasswordController) Get() {
|
||||
|
||||
resetUUID := rpc.GetString("reset_uuid")
|
||||
|
@ -198,6 +206,7 @@ func (rpc *ResetPasswordController) Get() {
|
|||
}
|
||||
}
|
||||
|
||||
// ResetPassword handles request from the reset page and reset password
|
||||
func (cc *CommonController) ResetPassword() {
|
||||
|
||||
resetUUID := cc.GetString("reset_uuid")
|
||||
|
|
|
@ -1,23 +1,25 @@
|
|||
/*
|
||||
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
package controllers
|
||||
|
||||
// ProjectController handles request to /registry/project
|
||||
type ProjectController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
// Get renders project page.
|
||||
func (p *ProjectController) Get() {
|
||||
p.Data["Username"] = p.GetSession("username")
|
||||
p.ForwardTo("page_title_project", "project")
|
||||
|
|
|
@ -25,10 +25,12 @@ import (
|
|||
"github.com/astaxie/beego"
|
||||
)
|
||||
|
||||
// RegisterController handles request to /register
|
||||
type RegisterController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
// Get renders the Sign In page, it only works if the auth mode is set to db_auth
|
||||
func (rc *RegisterController) Get() {
|
||||
authMode := os.Getenv("AUTH_MODE")
|
||||
if authMode == "" || authMode == "db_auth" {
|
||||
|
@ -38,6 +40,7 @@ func (rc *RegisterController) Get() {
|
|||
}
|
||||
}
|
||||
|
||||
// SignUp insert data into DB based on data in form.
|
||||
func (rc *CommonController) SignUp() {
|
||||
username := strings.TrimSpace(rc.GetString("username"))
|
||||
email := strings.TrimSpace(rc.GetString("email"))
|
||||
|
@ -54,6 +57,7 @@ func (rc *CommonController) SignUp() {
|
|||
}
|
||||
}
|
||||
|
||||
// UserExists checks if user exists when user input value in sign in form.
|
||||
func (rc *CommonController) UserExists() {
|
||||
target := rc.GetString("target")
|
||||
value := rc.GetString("value")
|
||||
|
|
|
@ -1,23 +1,25 @@
|
|||
/*
|
||||
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
package controllers
|
||||
|
||||
// SearchController handles request to /search
|
||||
type SearchController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
// Get renders page for displaying search result.
|
||||
func (sc *SearchController) Get() {
|
||||
sc.Data["Username"] = sc.GetSession("username")
|
||||
sc.Data["QueryParam"] = sc.GetString("q")
|
||||
|
|
|
@ -61,5 +61,5 @@ func init() {
|
|||
|
||||
//external service that hosted on harbor process:
|
||||
beego.Router("/service/notifications", &service.NotificationHandler{})
|
||||
beego.Router("/service/token", &service.AuthController{}, "get:Auth")
|
||||
beego.Router("/service/token", &service.TokenHandler{})
|
||||
}
|
||||
|
|
|
@ -25,12 +25,14 @@ import (
|
|||
"github.com/astaxie/beego"
|
||||
)
|
||||
|
||||
// NotificationHandler handles request on /service/notifications/, which listens to registry's events.
|
||||
type NotificationHandler struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
const MediaTypeManifest = "application/vnd.docker.distribution.manifest.v1+json"
|
||||
const mediaTypeManifest = "application/vnd.docker.distribution.manifest.v1+json"
|
||||
|
||||
// Post handles POST request, and records audit log or refreshes cache based on event.
|
||||
func (n *NotificationHandler) Post() {
|
||||
var notification models.Notification
|
||||
// log.Printf("Notification Handler triggered!\n")
|
||||
|
@ -43,7 +45,7 @@ func (n *NotificationHandler) Post() {
|
|||
}
|
||||
var username, action, repo, project string
|
||||
for _, e := range notification.Events {
|
||||
if e.Target.MediaType == MediaTypeManifest && strings.HasPrefix(e.Request.UserAgent, "docker") {
|
||||
if e.Target.MediaType == mediaTypeManifest && strings.HasPrefix(e.Request.UserAgent, "docker") {
|
||||
username = e.Actor.Name
|
||||
action = e.Action
|
||||
repo = e.Target.Repository
|
||||
|
@ -67,6 +69,7 @@ func (n *NotificationHandler) Post() {
|
|||
|
||||
}
|
||||
|
||||
// Render returns nil as it won't render any template.
|
||||
func (n *NotificationHandler) Render() error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -27,12 +27,15 @@ import (
|
|||
"github.com/docker/distribution/registry/auth/token"
|
||||
)
|
||||
|
||||
type AuthController struct {
|
||||
// TokenHandler handles request on /service/token, which is the auth provider for registry.
|
||||
type TokenHandler struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
//handle request
|
||||
func (a *AuthController) Auth() {
|
||||
// Get handles GET request, it checks the http header for user credentials
|
||||
// and parse service and scope based on docker registry v2 standard,
|
||||
// checkes the permission agains local DB and generates jwt token.
|
||||
func (a *TokenHandler) Get() {
|
||||
|
||||
request := a.Ctx.Request
|
||||
|
||||
|
@ -56,7 +59,7 @@ func (a *AuthController) Auth() {
|
|||
a.serveToken(username, service, access)
|
||||
}
|
||||
|
||||
func (a *AuthController) serveToken(username, service string, access []*token.ResourceActions) {
|
||||
func (a *TokenHandler) serveToken(username, service string, access []*token.ResourceActions) {
|
||||
writer := a.Ctx.ResponseWriter
|
||||
//create token
|
||||
rawToken, err := svc_utils.MakeToken(username, service, access)
|
|
@ -36,6 +36,7 @@ const (
|
|||
expiration = 5 //minute
|
||||
)
|
||||
|
||||
// GetResourceActions ...
|
||||
func GetResourceActions(scope string) []*token.ResourceActions {
|
||||
var res []*token.ResourceActions
|
||||
if scope == "" {
|
||||
|
@ -50,9 +51,8 @@ func GetResourceActions(scope string) []*token.ResourceActions {
|
|||
return res
|
||||
}
|
||||
|
||||
//Try to modify the action list in access based on permission
|
||||
//determine if the request needs to be authenticated.
|
||||
//for details see:https://github.com/docker/docker/issues/15640
|
||||
// FilterAccess modify the action list in access based on permission
|
||||
// determine if the request needs to be authenticated.
|
||||
func FilterAccess(username string, authenticated bool, a *token.ResourceActions) {
|
||||
|
||||
if a.Type == "registry" && a.Name == "catalog" {
|
||||
|
@ -98,7 +98,7 @@ func FilterAccess(username string, authenticated bool, a *token.ResourceActions)
|
|||
log.Printf("current access, type: %s, name:%s, actions:%v \n", a.Type, a.Name, a.Actions)
|
||||
}
|
||||
|
||||
//For the UI process to call, so it won't establish a https connection from UI to proxy.
|
||||
// GenTokenForUI is for the UI process to call, so it won't establish a https connection from UI to proxy.
|
||||
func GenTokenForUI(username, service, scope string) (string, error) {
|
||||
access := GetResourceActions(scope)
|
||||
for _, a := range access {
|
||||
|
@ -107,6 +107,7 @@ func GenTokenForUI(username, service, scope string) (string, error) {
|
|||
return MakeToken(username, service, access)
|
||||
}
|
||||
|
||||
// MakeToken makes a valid jwt token based on parms.
|
||||
func MakeToken(username, service string, access []*token.ResourceActions) (string, error) {
|
||||
pk, err := libtrust.LoadKeyFile(privateKey)
|
||||
if err != nil {
|
||||
|
|
|
@ -25,9 +25,10 @@ import (
|
|||
"github.com/astaxie/beego/cache"
|
||||
)
|
||||
|
||||
// Cache is the global cache in system.
|
||||
var Cache cache.Cache
|
||||
|
||||
const CATALOG string = "catalog"
|
||||
const catalogKey string = "catalog"
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
|
@ -37,6 +38,7 @@ func init() {
|
|||
}
|
||||
}
|
||||
|
||||
// RefreshCatalogCache calls registry's API to get repository list and write it to cache.
|
||||
func RefreshCatalogCache() error {
|
||||
result, err := RegistryAPIGet(BuildRegistryURL("_catalog"), "")
|
||||
if err != nil {
|
||||
|
@ -47,19 +49,20 @@ func RefreshCatalogCache() error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
Cache.Put(CATALOG, repoResp.Repositories, 600*time.Second)
|
||||
Cache.Put(catalogKey, repoResp.Repositories, 600*time.Second)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetRepoFromCache get repository list from cache, it refreshes the cache if it's empty.
|
||||
func GetRepoFromCache() ([]string, error) {
|
||||
|
||||
result := Cache.Get(CATALOG)
|
||||
result := Cache.Get(catalogKey)
|
||||
if result == nil {
|
||||
err := RefreshCatalogCache()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cached := Cache.Get(CATALOG)
|
||||
cached := Cache.Get(catalogKey)
|
||||
if cached != nil {
|
||||
return cached.([]string), nil
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// BuildRegistryURL ...
|
||||
func BuildRegistryURL(segments ...string) string {
|
||||
registryURL := os.Getenv("REGISTRY_URL")
|
||||
if registryURL == "" {
|
||||
|
@ -40,6 +41,8 @@ func BuildRegistryURL(segments ...string) string {
|
|||
return url
|
||||
}
|
||||
|
||||
// RegistryAPIGet triggers GET request to the URL which is the endpoint of registry and returns the response body.
|
||||
// It will attach a valid jwt token to the request if registry requires.
|
||||
func RegistryAPIGet(url, username string) ([]byte, error) {
|
||||
response, err := http.Get(url)
|
||||
if err != nil {
|
||||
|
|
Loading…
Reference in New Issue
Block a user