lib/ic/legacy.go (174 lines of code) (raw):
// Copyright 2019 Google LLC
//
// 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 ic
import (
"fmt"
"net/http"
"regexp"
"google.golang.org/grpc/status" /* copybara-comment */
"github.com/golang/protobuf/proto" /* copybara-comment */
"github.com/GoogleCloudPlatform/healthcare-federated-access-services/lib/ga4gh" /* copybara-comment: ga4gh */
"github.com/GoogleCloudPlatform/healthcare-federated-access-services/lib/handlerfactory" /* copybara-comment: handlerfactory */
"github.com/GoogleCloudPlatform/healthcare-federated-access-services/lib/httputils" /* copybara-comment: httputils */
"github.com/GoogleCloudPlatform/healthcare-federated-access-services/lib/storage" /* copybara-comment: storage */
cpb "github.com/GoogleCloudPlatform/healthcare-federated-access-services/proto/common/v1" /* copybara-comment: go_proto */
pb "github.com/GoogleCloudPlatform/healthcare-federated-access-services/proto/ic/v1" /* copybara-comment: go_proto */
)
// This file contains a number of legacy endpoints that will be removed.
var (
placeholderOrNameRE = regexp.MustCompile(`^(-|[A-Za-z][-_A-Za-z0-9\.]{1,30}[A-Za-z0-9])$`)
placeholderName = "-"
adminSubjectRE = regexp.MustCompile(`^[\w][^/\\]*@[\w][^/\\]*$`)
)
// HTTP handler for "/identity/v1alpha/{realm}/admin/subjects/{name}/account/claims"
func (s *Service) adminClaimsFactory() *handlerfactory.Options {
return &handlerfactory.Options{
TypeName: "adminClaims",
PathPrefix: adminClaimsPath,
HasNamedIdentifiers: false,
NameChecker: map[string]*regexp.Regexp{
"name": adminSubjectRE,
},
Service: func() handlerfactory.Service {
return &adminClaims{
s: s,
input: &pb.SubjectClaimsRequest{},
}
},
}
}
type adminClaims struct {
s *Service
item *cpb.Account
input *pb.SubjectClaimsRequest
save *cpb.Account
cfg *pb.IcConfig
id *ga4gh.Identity
tx storage.Tx
}
func (c *adminClaims) Setup(r *http.Request, tx storage.Tx) (int, error) {
cfg, _, id, status, err := c.s.handlerSetup(tx, r, noScope, c.input)
c.cfg = cfg
c.id = id
c.tx = tx
return status, err
}
func (c *adminClaims) LookupItem(r *http.Request, name string, vars map[string]string) bool {
acct, _, err := c.s.scim.LookupAccount(name, getRealm(r), true, c.tx)
if err != nil {
return false
}
c.item = acct
return true
}
func (c *adminClaims) NormalizeInput(r *http.Request, name string, vars map[string]string) error {
if err := httputils.DecodeProtoReq(c.input, r); err != nil {
return err
}
return nil
}
func (c *adminClaims) Get(r *http.Request, name string) (proto.Message, error) {
// Collect all claims across linked accounts.
out := []*cpb.Assertion{}
for _, link := range c.item.ConnectedAccounts {
if link.Passport == nil {
continue
}
for _, v := range link.Passport.Ga4GhAssertions {
out = append(out, v)
}
}
return &pb.SubjectClaimsResponse{Assertions: out}, nil
}
func (c *adminClaims) Post(r *http.Request, name string) (proto.Message, error) {
return nil, fmt.Errorf("POST not allowed")
}
func (c *adminClaims) Put(r *http.Request, name string) (proto.Message, error) {
return nil, fmt.Errorf("PUT not allowed")
}
func (c *adminClaims) Patch(r *http.Request, name string) (proto.Message, error) {
return nil, fmt.Errorf("PATCH not allowed")
}
func (c *adminClaims) Remove(r *http.Request, name string) (proto.Message, error) {
if c.input.Modification != nil && c.input.Modification.DryRun {
return nil, nil
}
c.save = &cpb.Account{}
proto.Merge(c.save, c.item)
for _, link := range c.save.ConnectedAccounts {
link.Passport = &cpb.Passport{}
}
return nil, nil
}
func (c *adminClaims) CheckIntegrity(*http.Request) *status.Status {
return nil
}
func (c *adminClaims) Save(r *http.Request, tx storage.Tx, name string, vars map[string]string, desc, typeName string) error {
if c.save == nil || (c.input.Modification != nil && c.input.Modification.DryRun) {
return nil
}
if err := c.s.scim.SaveAccount(c.item, c.save, desc, c.id.Subject, getRealm(r), r, c.tx); err != nil {
return err
}
return nil
}
// HTTP handler for "/identity/v1alpha/{realm}/admin/tokens"
func (s *Service) adminTokenMetadataFactory() *handlerfactory.Options {
return &handlerfactory.Options{
TypeName: "tokens",
PathPrefix: adminTokenMetadataPath,
HasNamedIdentifiers: false,
Service: func() handlerfactory.Service {
return &adminTokenMetadataHandler{
s: s,
input: &pb.TokensMetadataRequest{},
}
},
}
}
type adminTokenMetadataHandler struct {
s *Service
input *pb.TokensMetadataRequest
item map[string]*pb.TokenMetadata
tx storage.Tx
}
func (h *adminTokenMetadataHandler) Setup(r *http.Request, tx storage.Tx) (int, error) {
h.tx = tx
_, _, _, status, err := h.s.handlerSetup(tx, r, noScope, h.input)
return status, err
}
func (h *adminTokenMetadataHandler) LookupItem(r *http.Request, name string, vars map[string]string) bool {
h.item = make(map[string]*pb.TokenMetadata)
results, err := h.s.store.MultiReadTx(storage.TokensDatatype, getRealm(r), storage.DefaultUser, storage.MatchAllIDs, nil, 0, storage.MaxPageSize, &pb.TokenMetadata{}, h.tx)
if err != nil {
return false
}
for _, entry := range results.Entries {
if id, ok := entry.Item.(*pb.TokenMetadata); ok {
h.item[entry.GroupID+"/"+entry.ItemID] = id
}
}
return true
}
func (h *adminTokenMetadataHandler) NormalizeInput(r *http.Request, name string, vars map[string]string) error {
return httputils.DecodeProtoReq(h.input, r)
}
func (h *adminTokenMetadataHandler) Get(r *http.Request, name string) (proto.Message, error) {
item := h.item
if len(item) == 0 {
item = nil
}
return &pb.TokensMetadataResponse{TokensMetadata: item}, nil
}
func (h *adminTokenMetadataHandler) Post(r *http.Request, name string) (proto.Message, error) {
return nil, fmt.Errorf("POST not allowed")
}
func (h *adminTokenMetadataHandler) Put(r *http.Request, name string) (proto.Message, error) {
return nil, fmt.Errorf("PUT not allowed")
}
func (h *adminTokenMetadataHandler) Patch(r *http.Request, name string) (proto.Message, error) {
return nil, fmt.Errorf("PATCH not allowed")
}
func (h *adminTokenMetadataHandler) Remove(r *http.Request, name string) (proto.Message, error) {
return nil, h.s.store.MultiDeleteTx(storage.TokensDatatype, getRealm(r), storage.DefaultUser, h.tx)
}
func (h *adminTokenMetadataHandler) CheckIntegrity(*http.Request) *status.Status {
return nil
}
func (h *adminTokenMetadataHandler) Save(r *http.Request, tx storage.Tx, name string, vars map[string]string, desc, typeName string) error {
return nil
}