| OLD | NEW |
| 1 // Copyright 2016 The LUCI Authors. All rights reserved. | 1 // Copyright 2016 The LUCI Authors. All rights reserved. |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
| 3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
| 4 | 4 |
| 5 package buildbot | 5 package buildbot |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "bytes" | 8 "bytes" |
| 9 "compress/gzip" | 9 "compress/gzip" |
| 10 "encoding/json" | 10 "encoding/json" |
| 11 "fmt" | 11 "fmt" |
| 12 "sort" | 12 "sort" |
| 13 "time" | 13 "time" |
| 14 | 14 |
| 15 ds "github.com/luci/gae/service/datastore" | 15 ds "github.com/luci/gae/service/datastore" |
| 16 "github.com/luci/luci-go/common/logging" | 16 "github.com/luci/luci-go/common/logging" |
| 17 "github.com/luci/luci-go/milo/api/resp" | 17 "github.com/luci/luci-go/milo/api/resp" |
| 18 "github.com/luci/luci-go/milo/appengine/settings" | 18 "github.com/luci/luci-go/milo/appengine/settings" |
| 19 "github.com/luci/luci-go/server/auth" |
| 20 "github.com/luci/luci-go/server/auth/identity" |
| 19 | 21 |
| 20 "golang.org/x/net/context" | 22 "golang.org/x/net/context" |
| 21 ) | 23 ) |
| 22 | 24 |
| 23 func decodeMasterEntry( | 25 func decodeMasterEntry( |
| 24 c context.Context, entry *buildbotMasterEntry, master *buildbotMaster) e
rror { | 26 c context.Context, entry *buildbotMasterEntry, master *buildbotMaster) e
rror { |
| 25 | 27 |
| 26 reader, err := gzip.NewReader(bytes.NewReader(entry.Data)) | 28 reader, err := gzip.NewReader(bytes.NewReader(entry.Data)) |
| 27 if err != nil { | 29 if err != nil { |
| 28 return err | 30 return err |
| 29 } | 31 } |
| 30 defer reader.Close() | 32 defer reader.Close() |
| 31 if err = json.NewDecoder(reader).Decode(master); err != nil { | 33 if err = json.NewDecoder(reader).Decode(master); err != nil { |
| 32 return err | 34 return err |
| 33 } | 35 } |
| 34 return nil | 36 return nil |
| 35 } | 37 } |
| 36 | 38 |
| 39 // User not logged in, master found, master public: nil |
| 40 // User not logged in, master not found: 401 |
| 41 // User not logged in, master internal: 401 |
| 42 // User logged in, master found, master internal: nil |
| 43 // User logged in, master not found: 404 |
| 44 // User logged in, master found, master internal: 404 |
| 45 // Other error: 500 |
| 46 func checkAccess(c context.Context, err error, internal bool) error { |
| 47 cu := auth.CurrentUser(c) |
| 48 switch { |
| 49 case err == ds.ErrNoSuchEntity: |
| 50 if cu.Identity == identity.AnonymousIdentity { |
| 51 return errNotAuth |
| 52 } else { |
| 53 return errMasterNotFound |
| 54 } |
| 55 case err != nil: |
| 56 return err |
| 57 } |
| 58 |
| 59 // Do the ACL check if the entry is internal. |
| 60 if internal { |
| 61 allowed, err := settings.IsAllowedInternal(c) |
| 62 if err != nil { |
| 63 return err |
| 64 } |
| 65 if !allowed { |
| 66 if cu.Identity == identity.AnonymousIdentity { |
| 67 return errNotAuth |
| 68 } else { |
| 69 return errMasterNotFound |
| 70 } |
| 71 } |
| 72 } |
| 73 |
| 74 return nil |
| 75 } |
| 76 |
| 37 // getMasterEntry feches the named master and does an ACL check on the | 77 // getMasterEntry feches the named master and does an ACL check on the |
| 38 // current user. | 78 // current user. |
| 79 // It returns: |
| 39 func getMasterEntry(c context.Context, name string) (*buildbotMasterEntry, error
) { | 80 func getMasterEntry(c context.Context, name string) (*buildbotMasterEntry, error
) { |
| 40 entry := buildbotMasterEntry{Name: name} | 81 entry := buildbotMasterEntry{Name: name} |
| 41 err := ds.Get(c, &entry) | 82 err := ds.Get(c, &entry) |
| 42 » switch { | 83 » err = checkAccess(c, err, entry.Internal) |
| 43 » case err == ds.ErrNoSuchEntity: | 84 » return &entry, err |
| 44 » » return nil, errMasterNotFound | |
| 45 » case err != nil: | |
| 46 » » logging.WithError(err).Errorf( | |
| 47 » » » c, "Encountered error while fetching entry for %s:\n%s",
name, err) | |
| 48 » » return nil, err | |
| 49 » } | |
| 50 | |
| 51 » // Do the ACL check if the entry is internal. | |
| 52 » if entry.Internal { | |
| 53 » » allowed, err := settings.IsAllowedInternal(c) | |
| 54 » » if err != nil { | |
| 55 » » » return nil, err | |
| 56 » » } | |
| 57 » » if !allowed { | |
| 58 » » » return nil, errMasterNotFound | |
| 59 » » } | |
| 60 » } | |
| 61 | |
| 62 » return &entry, nil | |
| 63 } | 85 } |
| 64 | 86 |
| 65 // getMasterJSON fetches the latest known buildbot master data and returns | 87 // getMasterJSON fetches the latest known buildbot master data and returns |
| 66 // the buildbotMaster struct (if found), whether or not it is internal, | 88 // the buildbotMaster struct (if found), whether or not it is internal, |
| 67 // the last modified time, and an error if not found. | 89 // the last modified time, and an error if not found. |
| 68 func getMasterJSON(c context.Context, name string) ( | 90 func getMasterJSON(c context.Context, name string) ( |
| 69 master *buildbotMaster, t time.Time, err error) { | 91 master *buildbotMaster, t time.Time, err error) { |
| 70 master = &buildbotMaster{} | 92 master = &buildbotMaster{} |
| 71 entry, err := getMasterEntry(c, name) | 93 entry, err := getMasterEntry(c, name) |
| 72 if err != nil { | 94 if err != nil { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 Label: bn, | 145 Label: bn, |
| 124 // Go templates escapes this for us, and also | 146 // Go templates escapes this for us, and also |
| 125 // slashes are not allowed in builder names. | 147 // slashes are not allowed in builder names. |
| 126 URL: fmt.Sprintf("/buildbot/%s/%s", entry.Name,
bn), | 148 URL: fmt.Sprintf("/buildbot/%s/%s", entry.Name,
bn), |
| 127 }) | 149 }) |
| 128 } | 150 } |
| 129 result.Masters = append(result.Masters, ml) | 151 result.Masters = append(result.Masters, ml) |
| 130 } | 152 } |
| 131 return result, nil | 153 return result, nil |
| 132 } | 154 } |
| OLD | NEW |