git.frostfs.info/TrueCloudLab/frostfs-sdk-go@v0.0.0-20241022124111-5361f0ecebd3/client/session.go (about)

     1  package client
     2  
     3  import (
     4  	"context"
     5  	"crypto/ecdsa"
     6  	"fmt"
     7  
     8  	"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
     9  	rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
    10  	"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
    11  	v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
    12  	"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
    13  	apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
    14  	"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
    15  )
    16  
    17  // PrmSessionCreate groups parameters of SessionCreate operation.
    18  type PrmSessionCreate struct {
    19  	XHeaders []string
    20  
    21  	Expiration uint64
    22  
    23  	Key *ecdsa.PrivateKey
    24  }
    25  
    26  // SetExp sets number of the last NepFS epoch in the lifetime of the session after which it will be expired.
    27  //
    28  // Deprecated: Use PrmSessionCreate.Expiration instead.
    29  func (x *PrmSessionCreate) SetExp(exp uint64) {
    30  	x.Expiration = exp
    31  }
    32  
    33  // UseKey specifies private key to sign the requests and compute token owner.
    34  // If key is not provided, then Client default key is used.
    35  //
    36  // Deprecated: Use PrmSessionCreate.Key instead.
    37  func (x *PrmSessionCreate) UseKey(key ecdsa.PrivateKey) {
    38  	x.Key = &key
    39  }
    40  
    41  func (x *PrmSessionCreate) buildRequest(c *Client) (*v2session.CreateRequest, error) {
    42  	ownerKey := c.prm.Key.PublicKey
    43  	if x.Key != nil {
    44  		ownerKey = x.Key.PublicKey
    45  	}
    46  	var ownerID user.ID
    47  	user.IDFromKey(&ownerID, ownerKey)
    48  
    49  	var ownerIDV2 refs.OwnerID
    50  	ownerID.WriteToV2(&ownerIDV2)
    51  
    52  	reqBody := new(v2session.CreateRequestBody)
    53  	reqBody.SetOwnerID(&ownerIDV2)
    54  	reqBody.SetExpiration(x.Expiration)
    55  
    56  	var meta v2session.RequestMetaHeader
    57  	writeXHeadersToMeta(x.XHeaders, &meta)
    58  
    59  	var req v2session.CreateRequest
    60  	req.SetBody(reqBody)
    61  	c.prepareRequest(&req, &meta)
    62  	return &req, nil
    63  }
    64  
    65  // ResSessionCreate groups resulting values of SessionCreate operation.
    66  type ResSessionCreate struct {
    67  	statusRes
    68  
    69  	id []byte
    70  
    71  	sessionKey []byte
    72  }
    73  
    74  // ID returns identifier of the opened session in a binary FrostFS API protocol format.
    75  //
    76  // Client doesn't retain value so modification is safe.
    77  func (x ResSessionCreate) ID() []byte {
    78  	return x.id
    79  }
    80  
    81  // PublicKey returns public key of the opened session in a binary FrostFS API protocol format.
    82  func (x ResSessionCreate) PublicKey() []byte {
    83  	return x.sessionKey
    84  }
    85  
    86  // SessionCreate opens a session with the node server on the remote endpoint.
    87  // The session lifetime coincides with the server lifetime. Results can be written
    88  // to session token which can be later attached to the requests.
    89  //
    90  // Exactly one return value is non-nil. By default, server status is returned in res structure.
    91  // Any client's internal or transport errors are returned as `error`.
    92  // If PrmInit.DisableFrostFSFailuresResolution has been called, unsuccessful
    93  // FrostFS status codes are included in the returned result structure,
    94  // otherwise, are also returned as `error`.
    95  //
    96  // Returns an error if parameters are set incorrectly (see PrmSessionCreate docs).
    97  // Context is required and must not be nil. It is used for network communication.
    98  //
    99  // Return statuses:
   100  //   - global (see Client docs).
   101  func (c *Client) SessionCreate(ctx context.Context, prm PrmSessionCreate) (*ResSessionCreate, error) {
   102  	req, err := prm.buildRequest(c)
   103  	if err != nil {
   104  		return nil, err
   105  	}
   106  
   107  	if err := signature.SignServiceMessage(&c.prm.Key, req); err != nil {
   108  		return nil, fmt.Errorf("sign request: %w", err)
   109  	}
   110  
   111  	resp, err := rpcapi.CreateSession(&c.c, req, client.WithContext(ctx))
   112  	if err != nil {
   113  		return nil, err
   114  	}
   115  
   116  	var res ResSessionCreate
   117  	res.st, err = c.processResponse(resp)
   118  	if err != nil || !apistatus.IsSuccessful(res.st) {
   119  		return &res, err
   120  	}
   121  
   122  	body := resp.GetBody()
   123  	res.id = body.GetID()
   124  	res.sessionKey = body.GetSessionKey()
   125  	return &res, nil
   126  }