mirror of
https://github.com/goharbor/harbor.git
synced 2025-01-22 15:41:26 +01:00
add statistic api for projects and repos
This commit is contained in:
parent
f6a1b1c4e4
commit
be6bf2ab22
@ -1,15 +1,35 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICWDCCAcGgAwIBAgIJAN1nLuloDeHNMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
|
||||
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
|
||||
aWRnaXRzIFB0eSBMdGQwHhcNMTYwMTI3MDQyMDM1WhcNNDMwNjE0MDQyMDM1WjBF
|
||||
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
|
||||
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
|
||||
gQClak/4HO7EeLU0w/BhtVENPLOqU0AP2QjVUdg1qhNiDWVrbWx9KYHqz5Kn0n2+
|
||||
fxdZo3o7ZY5/2+hhgkKh1z6Kge9XGgune6z4fx2J/X2Se8WsGeQUTiND8ngSnsCA
|
||||
NtYFwW50SbUZPtyf5XjAfKRofZem51OxbxzN3217L/ubKwIDAQABo1AwTjAdBgNV
|
||||
HQ4EFgQU5EG2VrB3I6G/TudUpz+kBgQXSvYwHwYDVR0jBBgwFoAU5EG2VrB3I6G/
|
||||
TudUpz+kBgQXSvYwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQAx+2eo
|
||||
oOm0YNy9KQ81+7GQkKVWoPQXjAGGgZuZj8WCFepYqUSJ4q5qbuVCY8WbGcHVk2Rx
|
||||
Jg1XDCmMjBgYP6S0ikezBRqSmNA3G6oFiydTKBfPs6RNalsB0C78Xk5l5+PIyd2R
|
||||
jFKOKoMpkjwfeJv2j64WNGoBgqj7XRBoJ11a4g==
|
||||
MIIGBzCCA++gAwIBAgIJANjBN67MD5SgMA0GCSqGSIb3DQEBCwUAMIGZMQswCQYD
|
||||
VQQGEwJDTjEOMAwGA1UECAwFU3RhdGUxCzAJBgNVBAcMAkNOMRUwEwYDVQQKDAxv
|
||||
cmdhbml6YXRpb24xHDAaBgNVBAsME29yZ2FuaXphdGlvbmFsIHVuaXQxFDASBgNV
|
||||
BAMMC2V4YW1wbGUuY29tMSIwIAYJKoZIhvcNAQkBFhNleGFtcGxlQGV4YW1wbGUu
|
||||
Y29tMB4XDTE2MDUxMDA0MTMxM1oXDTI2MDUwODA0MTMxM1owgZkxCzAJBgNVBAYT
|
||||
AkNOMQ4wDAYDVQQIDAVTdGF0ZTELMAkGA1UEBwwCQ04xFTATBgNVBAoMDG9yZ2Fu
|
||||
aXphdGlvbjEcMBoGA1UECwwTb3JnYW5pemF0aW9uYWwgdW5pdDEUMBIGA1UEAwwL
|
||||
ZXhhbXBsZS5jb20xIjAgBgkqhkiG9w0BCQEWE2V4YW1wbGVAZXhhbXBsZS5jb20w
|
||||
ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDVSMUP/IR3iGdM4WrvuWno
|
||||
Jy+mjOV/Qcte8gK92ClKd5zObAlo6/hn8ZMTeub76A9i39QN8GlQDFMtfv29EpLn
|
||||
XXoVvLIwH4olycSdrye0ustOke/KT2RHAl3cVi5Zau0rfnb6h5kPQFFgjHsFdsLi
|
||||
KIOBru976pJh3qxXq2xHIbmHvqLLEGuvt2WKXiRyz9ex6zbc/RTQhesJIA/N73Xo
|
||||
9m5TfKOimuTedHYuGwS9XAHdr0W+EZl39keaPemrJz5QcebwwZPApuGwe0We8koL
|
||||
0W1b2Z1a/gUdjcE++RVDOpHCupB/MltB+FSBJKd6LIbkjV1AC+T3NB3CzDPUP/Ep
|
||||
bjk4wJqGOmMS+/mZbVu9lybrem7V0Wc03DEQyjZztpBcQ6MFbVw3pIbp3fAWhyDJ
|
||||
N1y+i0O1Llcybpje5P3fQ0ioYc3hF61Wj3bAAx7ddPmrmtVGgisfvcTIRjNLGylM
|
||||
qObhRjPPvky03x2jtwTnPX74gowuqq70sZHjfqpmXrjpJi9RMEJz30dxW6gy9Mn+
|
||||
MOTzwJ7iu3sm6XidaogMvMFrVlLfgIVLl+WfZJIv+i2by6TXfZ6/5OTvU4fzc1NZ
|
||||
VeWBUSznmM/V72sWc/3AFgNibysv95OwDohqy91N9U73P6Q8H96hkDVHHhktHSL6
|
||||
s1OQau9XDgKS6xhZZsRxlwIDAQABo1AwTjAdBgNVHQ4EFgQUQl1pgU1b+rJMvLsQ
|
||||
W1YednSAsDUwHwYDVR0jBBgwFoAUQl1pgU1b+rJMvLsQW1YednSAsDUwDAYDVR0T
|
||||
BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAxCMLH/BhxzAGI2k8oBUXOaFXB+uo
|
||||
2hrteE4glQw0nY959y7FEgKYBKKktWRqNBB/FlNSsrritfhWNK04tIHDQtUhP09m
|
||||
2TD/0bxY++i+cyhqflHnyROkhAtcg1SBDhwkDMyEKnjzEe7t80Vq6d2sEBbq4PcA
|
||||
Owl9Xj8elTt1g6aKP4Wt1V7ktZG+zAct+VPQtCnXCH2GAbkN8zqYKpCmzW0IBy0D
|
||||
NFWKjsebXawOjUwMFu9MTDIwU3DvcCcrNj8k1palLPNNuyXqbsmencFjDRe2mZDU
|
||||
lA2l4bpZ4G4HPSUJmhZHQ7eq9CYr5goS+kI36n5Uvg2TDDQQxXtfugRkI1qqxGlU
|
||||
w+qc5BeQqkBior/dI/70+z0ith8/qZZ4U+y7eYY2lzIaNAOn2YLIdxkjF4YxIbSu
|
||||
kV+Flxa4pFookeLvucZP1v3yW9VdHwClRGD4S4yiGC4j5uG8kcyRssH+iwdTm4Bl
|
||||
0PSYiseeb0xlDaZMMq4K1IRvPLZ4PBKe+I6db8TIsTQjLIx8cUKaMdJlBUVLnmVG
|
||||
uKKxdNz0OBUykEMAltHSagp/QqmVCED/q+Y1dsR2c2jy48dKl0mNRSTxMyaO1DTA
|
||||
Fuzq0uQJetQdgwEdnoU0nabDk56vP686g4rJR8N6r822JxIfpE6ZLasgBX9P4jJS
|
||||
rbSyDwCgpBd5p2g=
|
||||
-----END CERTIFICATE-----
|
||||
|
@ -1,15 +1,51 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
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
|
||||
-----END RSA PRIVATE KEY-----
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#The IP address or hostname to access admin UI and registry service.
|
||||
#DO NOT use localhost or 127.0.0.1, because Harbor needs to be accessed by external clients.
|
||||
hostname = reg.mydomain.com
|
||||
hostname = localhost
|
||||
|
||||
#The protocol for accessing the UI and token/notification service, by default it is http.
|
||||
#It can be set to https if ssl is enabled on nginx.
|
||||
|
146
api/statistic.go
Normal file
146
api/statistic.go
Normal file
@ -0,0 +1,146 @@
|
||||
/*
|
||||
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 api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/vmware/harbor/dao"
|
||||
"github.com/vmware/harbor/models"
|
||||
svc_utils "github.com/vmware/harbor/service/utils"
|
||||
"github.com/vmware/harbor/utils/log"
|
||||
"github.com/vmware/harbor/utils/registry"
|
||||
"github.com/vmware/harbor/utils/registry/auth"
|
||||
)
|
||||
|
||||
type StatisticAPI struct {
|
||||
BaseAPI
|
||||
userID int
|
||||
username string
|
||||
registry *registry.Registry
|
||||
}
|
||||
|
||||
//Prepare validates the URL and the user
|
||||
func (s *StatisticAPI) Prepare() {
|
||||
userID, ok := s.GetSession("userId").(int)
|
||||
if !ok {
|
||||
s.userID = dao.NonExistUserID
|
||||
} else {
|
||||
s.userID = userID
|
||||
log.Debug("userID is xxx", userID)
|
||||
}
|
||||
username, ok := s.GetSession("username").(string)
|
||||
if !ok {
|
||||
log.Warning("failed to get username from session")
|
||||
s.username = ""
|
||||
} else {
|
||||
s.username = username
|
||||
log.Debug("username is xxx", username)
|
||||
}
|
||||
|
||||
var client *http.Client
|
||||
|
||||
//no session, initialize a standard auth handler
|
||||
if s.userID == dao.NonExistUserID && len(s.username) == 0 {
|
||||
username, password, _ := s.Ctx.Request.BasicAuth()
|
||||
|
||||
credential := auth.NewBasicAuthCredential(username, password)
|
||||
client = registry.NewClientStandardAuthHandlerEmbeded(credential)
|
||||
log.Debug("initializing standard auth handler")
|
||||
|
||||
} else {
|
||||
// session works, initialize a username auth handler
|
||||
username := s.username
|
||||
if len(username) == 0 {
|
||||
user, err := dao.GetUser(models.User{
|
||||
UserID: s.userID,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("error occurred whiling geting user for initializing a username auth handler: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
username = user.Username
|
||||
}
|
||||
|
||||
client = registry.NewClientUsernameAuthHandlerEmbeded(username)
|
||||
log.Debug("initializing username auth handler: %s", username)
|
||||
}
|
||||
|
||||
endpoint := os.Getenv("REGISTRY_URL")
|
||||
r, err := registry.New(endpoint, client)
|
||||
if err != nil {
|
||||
log.Fatalf("error occurred while initializing auth handler for repository API: %v", err)
|
||||
}
|
||||
|
||||
s.registry = r
|
||||
}
|
||||
|
||||
// Get total projects and repos of the user
|
||||
func (s *StatisticAPI) Get() {
|
||||
queryProject := models.Project{UserID: s.userID}
|
||||
projectList, err := dao.QueryProject(queryProject)
|
||||
var projectArr [6]int
|
||||
if err != nil {
|
||||
log.Errorf("Error occured in QueryProject, error: %v", err)
|
||||
s.CustomAbort(http.StatusInternalServerError, "Internal error.")
|
||||
}
|
||||
log.Debug("projectList xxx ", projectList)
|
||||
isAdmin, _ := dao.IsAdminRole(s.userID)
|
||||
for i := 0; i < len(projectList); i++ {
|
||||
if isProjectAdmin(s.userID, projectList[i].ProjectID) {
|
||||
projectArr[0] += 1
|
||||
projectArr[1] += s.GetRepos(projectList[i].ProjectID)
|
||||
}
|
||||
if projectList[i].Public == 1 {
|
||||
projectArr[2] += 1
|
||||
projectArr[3] += s.GetRepos(projectList[i].ProjectID)
|
||||
}
|
||||
if isAdmin {
|
||||
projectArr[5] += s.GetRepos(projectList[i].ProjectID)
|
||||
}
|
||||
}
|
||||
if isAdmin {
|
||||
projectArr[4] = len(projectList)
|
||||
}
|
||||
s.Data["json"] = projectArr
|
||||
s.ServeJSON()
|
||||
}
|
||||
|
||||
func (s *StatisticAPI) GetRepos(projectID int64) int {
|
||||
p, err := dao.GetProjectByID(projectID)
|
||||
if err != nil {
|
||||
log.Errorf("Error occurred in GetProjectById, error: %v", err)
|
||||
s.CustomAbort(http.StatusInternalServerError, "Internal error.")
|
||||
}
|
||||
if p == nil {
|
||||
log.Warningf("Project with Id: %d does not exist", projectID)
|
||||
s.RenderError(http.StatusNotFound, "")
|
||||
return 0
|
||||
}
|
||||
if p.Public == 0 && !checkProjectPermission(s.userID, projectID) {
|
||||
s.RenderError(http.StatusForbidden, "")
|
||||
return 0
|
||||
}
|
||||
|
||||
repoList, err := svc_utils.GetRepoFromCache()
|
||||
if err != nil {
|
||||
log.Errorf("Failed to get repo from cache, error: %v", err)
|
||||
s.RenderError(http.StatusInternalServerError, "internal sever error")
|
||||
}
|
||||
return len(repoList)
|
||||
}
|
@ -54,6 +54,7 @@ func initRouters() {
|
||||
beego.Router("/api/search", &api.SearchAPI{})
|
||||
beego.Router("/api/projects/:pid/members/?:mid", &api.ProjectMemberAPI{})
|
||||
beego.Router("/api/projects/?:id", &api.ProjectAPI{})
|
||||
beego.Router("/api/statistics", &api.StatisticAPI{})
|
||||
beego.Router("/api/projects/:id/logs/filter", &api.ProjectAPI{}, "post:FilterAccessLog")
|
||||
beego.Router("/api/users", &api.UserAPI{})
|
||||
beego.Router("/api/users/?:id", &api.UserAPI{})
|
||||
|
Loading…
Reference in New Issue
Block a user