Index: appengine/logdog/coordinator/auth.go |
diff --git a/appengine/logdog/coordinator/auth.go b/appengine/logdog/coordinator/auth.go |
index 6c60d88ca59d415af90a354108c0e55131d3f090..6f85e80928ed24d3e9b23430b938e45206d207f3 100644 |
--- a/appengine/logdog/coordinator/auth.go |
+++ b/appengine/logdog/coordinator/auth.go |
@@ -5,85 +5,99 @@ |
package coordinator |
import ( |
- "errors" |
"fmt" |
+ "strings" |
"github.com/luci/gae/service/info" |
- "github.com/luci/luci-go/appengine/logdog/coordinator/config" |
+ luciConfig "github.com/luci/luci-go/common/config" |
log "github.com/luci/luci-go/common/logging" |
- "github.com/luci/luci-go/common/proto/logdog/svcconfig" |
"github.com/luci/luci-go/server/auth" |
"github.com/luci/luci-go/server/auth/identity" |
"golang.org/x/net/context" |
) |
-// ErrNoAccess is returned if the user has no access to the requested project. |
-var ErrNoAccess = config.ErrNoAccess |
- |
// IsAdminUser tests whether the current user belongs to the administrative |
-// users group. It will return an error if the user does not. |
+// users group. |
+// |
+// If the user is not a member of any groups, a MembershipError will be |
nodir
2016/05/19 00:38:58
which "any groups" you are referring to in the con
dnj (Google)
2016/05/19 16:12:34
Done.
|
+// returned. |
func IsAdminUser(c context.Context) error { |
- return isMember(c, func(cfg *svcconfig.Coordinator) string { |
- return cfg.AdminAuthGroup |
- }) |
+ cfg, err := GetServices(c).Config(c) |
+ if err != nil { |
+ return err |
+ } |
+ return checkMember(c, cfg.Coordinator.AdminAuthGroup) |
} |
// IsServiceUser tests whether the current user belongs to the backend services |
-// users group. It will return an error if the user does not. |
+// users group. |
+// |
+// If the user is not a member of any groups, a MembershipError will be |
nodir
2016/05/19 00:38:58
same here
dnj (Google)
2016/05/19 16:12:34
Done.
|
+// returned. |
func IsServiceUser(c context.Context) error { |
- return isMember(c, func(cfg *svcconfig.Coordinator) string { |
- return cfg.ServiceAuthGroup |
- }) |
+ cfg, err := GetServices(c).Config(c) |
+ if err != nil { |
+ return err |
+ } |
+ return checkMember(c, cfg.Coordinator.ServiceAuthGroup) |
} |
-func isMember(c context.Context, groupNameFunc func(*svcconfig.Coordinator) string) error { |
+// IsProjectReader tests whether the current user belongs to one of the |
+// project's declared reader groups. |
+// |
+// If the user is not a member of any groups, a MembershipError will be |
nodir
2016/05/19 00:38:58
english: "any group"?
dnj (Google)
2016/05/19 16:12:34
Yeah this comment has gone through a few stages of
|
+// returned. |
+func IsProjectReader(c context.Context, project luciConfig.ProjectName) error { |
+ pcfg, err := GetServices(c).ProjectConfig(c, project) |
+ if err != nil { |
+ return err |
+ } |
+ return checkMember(c, pcfg.ReaderAuthGroups...) |
+} |
+ |
+func checkMember(c context.Context, groups ...string) error { |
// On dev-appserver, the superuser has implicit group membership to |
// everything. |
if info.Get(c).IsDevAppServer() { |
if u := auth.CurrentUser(c); u.Superuser { |
log.Fields{ |
"identity": u.Identity, |
+ "groups": groups, |
}.Infof(c, "Granting superuser implicit group membership on development server.") |
return nil |
} |
} |
- cfg, err := GetServices(c).Config(c) |
- if err != nil { |
- return err |
- } |
- |
- if cfg.Coordinator == nil { |
- return errors.New("no coordinator configuration") |
- } |
- |
- groupName := groupNameFunc(cfg.Coordinator) |
- if groupName == "" { |
- return errors.New("no auth group is configured") |
+ id := auth.CurrentIdentity(c) |
+ for _, group := range groups { |
+ is, err := auth.IsMember(c, group) |
+ if err != nil { |
+ return err |
+ } |
+ if is { |
+ log.Fields{ |
+ "identity": id, |
+ "group": group, |
+ }.Debugf(c, "User access granted.") |
+ return nil |
+ } |
} |
- is, err := auth.IsMember(c, groupName) |
- if err != nil { |
- return err |
- } |
- if !is { |
- return &MembershipError{ |
- Identity: auth.CurrentIdentity(c), |
- Group: groupName, |
- } |
+ return &MembershipError{ |
+ Identity: id, |
+ Groups: groups, |
} |
- return nil |
} |
// MembershipError is an error returned by group membership checking functions |
// if the current identity is not a member of the requested group. |
type MembershipError struct { |
Identity identity.Identity |
- Group string |
+ Groups []string |
} |
func (e *MembershipError) Error() string { |
- return fmt.Sprintf("user %q is not a member of group %q", e.Identity, e.Group) |
+ return fmt.Sprintf("user %q is not a member of [%s]", e.Identity, strings.Join(e.Groups, ", ")) |
} |
// IsMembershipError returns whether a given error is a membership error. |