add statistic api for projects and repos

This commit is contained in:
wemeya 2016-05-10 15:10:19 +08:00
parent f6a1b1c4e4
commit be6bf2ab22
5 changed files with 230 additions and 27 deletions

View File

@ -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-----

View File

@ -1,15 +1,51 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

View File

@ -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
View 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)
}

View File

@ -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{})