github.com/cs3org/reva/v2@v2.27.7/pkg/sdk/session.go (about)

     1  // Copyright 2018-2021 CERN
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  // In applying this license, CERN does not waive the privileges and immunities
    16  // granted to it by virtue of its status as an Intergovernmental Organization
    17  // or submit itself to any jurisdiction.
    18  
    19  package sdk
    20  
    21  import (
    22  	"context"
    23  	"crypto/tls"
    24  	"fmt"
    25  	"io"
    26  
    27  	registry "github.com/cs3org/go-cs3apis/cs3/auth/registry/v1beta1"
    28  	gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
    29  	"google.golang.org/grpc"
    30  	"google.golang.org/grpc/credentials"
    31  	"google.golang.org/grpc/credentials/insecure"
    32  	"google.golang.org/grpc/metadata"
    33  
    34  	"github.com/cs3org/reva/v2/pkg/sdk/common"
    35  	"github.com/cs3org/reva/v2/pkg/sdk/common/net"
    36  )
    37  
    38  // Session stores information about a Reva session.
    39  // It is also responsible for managing the Reva gateway client.
    40  type Session struct {
    41  	ctx    context.Context
    42  	client gateway.GatewayAPIClient
    43  
    44  	token string
    45  }
    46  
    47  func (session *Session) initSession(ctx context.Context) error {
    48  	session.ctx = ctx
    49  
    50  	return nil
    51  }
    52  
    53  // Initiate initiates the session by creating a connection to the host and preparing the gateway client.
    54  func (session *Session) Initiate(host string, insecure bool) error {
    55  	conn, err := session.getConnection(host, insecure)
    56  	if err != nil {
    57  		return fmt.Errorf("unable to establish a gRPC connection to '%v': %v", host, err)
    58  	}
    59  	session.client = gateway.NewGatewayAPIClient(conn)
    60  
    61  	return nil
    62  }
    63  
    64  func (session *Session) getConnection(host string, ins bool) (*grpc.ClientConn, error) {
    65  	if ins {
    66  		return grpc.NewClient(host, grpc.WithTransportCredentials(insecure.NewCredentials()))
    67  	}
    68  
    69  	tlsconf := &tls.Config{InsecureSkipVerify: false}
    70  	creds := credentials.NewTLS(tlsconf)
    71  	return grpc.NewClient(host, grpc.WithTransportCredentials(creds))
    72  }
    73  
    74  // GetLoginMethods returns a list of all available login methods supported by the Reva instance.
    75  func (session *Session) GetLoginMethods() ([]string, error) {
    76  	req := &registry.ListAuthProvidersRequest{}
    77  	res, err := session.client.ListAuthProviders(session.ctx, req)
    78  	if err := net.CheckRPCInvocation("listing authorization providers", res, err); err != nil {
    79  		return []string{}, err
    80  	}
    81  
    82  	return res.Types, nil
    83  }
    84  
    85  // Login logs into Reva using the specified method and user credentials.
    86  func (session *Session) Login(method string, username string, password string) error {
    87  	req := &gateway.AuthenticateRequest{
    88  		Type:         method,
    89  		ClientId:     username,
    90  		ClientSecret: password,
    91  	}
    92  	res, err := session.client.Authenticate(session.ctx, req)
    93  	if err := net.CheckRPCInvocation("authenticating", res, err); err != nil {
    94  		return err
    95  	}
    96  
    97  	if res.Token == "" {
    98  		return fmt.Errorf("invalid token received: %q", res.Token)
    99  	}
   100  	session.token = res.Token
   101  
   102  	// Now that we have a valid token, we can append this to our context
   103  	session.ctx = context.WithValue(session.ctx, net.AccessTokenIndex, session.token)
   104  	session.ctx = metadata.AppendToOutgoingContext(session.ctx, net.AccessTokenName, session.token)
   105  
   106  	return nil
   107  }
   108  
   109  // BasicLogin tries to log into Reva using basic authentication.
   110  // Before the actual login attempt, the method verifies that the Reva instance does support the "basic" login method.
   111  func (session *Session) BasicLogin(username string, password string) error {
   112  	// Check if the 'basic' method is actually supported by the Reva instance; only continue if this is the case
   113  	supportedMethods, err := session.GetLoginMethods()
   114  	if err != nil {
   115  		return fmt.Errorf("unable to get a list of all supported login methods: %v", err)
   116  	}
   117  
   118  	if common.FindStringNoCase(supportedMethods, "basic") == -1 {
   119  		return fmt.Errorf("'basic' login method is not supported")
   120  	}
   121  
   122  	return session.Login("basic", username, password)
   123  }
   124  
   125  // NewHTTPRequest returns an HTTP request instance.
   126  func (session *Session) NewHTTPRequest(endpoint string, method string, transportToken string, data io.Reader) (*net.HTTPRequest, error) {
   127  	return net.NewHTTPRequest(session.ctx, endpoint, method, session.token, transportToken, data)
   128  }
   129  
   130  // Client gets the gateway client instance.
   131  func (session *Session) Client() gateway.GatewayAPIClient {
   132  	return session.client
   133  }
   134  
   135  // Context returns the session context.
   136  func (session *Session) Context() context.Context {
   137  	return session.ctx
   138  }
   139  
   140  // Token returns the session token.
   141  func (session *Session) Token() string {
   142  	return session.token
   143  }
   144  
   145  // IsValid checks whether the session has been initialized and fully established.
   146  func (session *Session) IsValid() bool {
   147  	return session.client != nil && session.ctx != nil && session.token != ""
   148  }
   149  
   150  // NewSessionWithContext creates a new Reva session using the provided context.
   151  func NewSessionWithContext(ctx context.Context) (*Session, error) {
   152  	session := &Session{}
   153  	if err := session.initSession(ctx); err != nil {
   154  		return nil, fmt.Errorf("unable to initialize the session: %v", err)
   155  	}
   156  	return session, nil
   157  }
   158  
   159  // NewSession creates a new Reva session using a default background context.
   160  func NewSession() (*Session, error) {
   161  	return NewSessionWithContext(context.Background())
   162  }
   163  
   164  // MustNewSession creates a new session and panics on failure.
   165  func MustNewSession() *Session {
   166  	session, err := NewSession()
   167  	if err != nil {
   168  		panic(err)
   169  	}
   170  	return session
   171  }