requests.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. package tokens
  2. import "devel.mephi.ru/iacherepanov/openstack-gophercloud"
  3. // Scope allows a created token to be limited to a specific domain or project.
  4. type Scope struct {
  5. ProjectID string
  6. ProjectName string
  7. DomainID string
  8. DomainName string
  9. }
  10. // AuthOptionsBuilder provides the ability for extensions to add additional
  11. // parameters to AuthOptions. Extensions must satisfy all required methods.
  12. type AuthOptionsBuilder interface {
  13. // ToTokenV3CreateMap assembles the Create request body, returning an error
  14. // if parameters are missing or inconsistent.
  15. ToTokenV3CreateMap(map[string]interface{}) (map[string]interface{}, error)
  16. ToTokenV3ScopeMap() (map[string]interface{}, error)
  17. CanReauth() bool
  18. }
  19. // AuthOptions represents options for authenticating a user.
  20. type AuthOptions struct {
  21. // IdentityEndpoint specifies the HTTP endpoint that is required to work with
  22. // the Identity API of the appropriate version. While it's ultimately needed
  23. // by all of the identity services, it will often be populated by a
  24. // provider-level function.
  25. IdentityEndpoint string `json:"-"`
  26. // Username is required if using Identity V2 API. Consult with your provider's
  27. // control panel to discover your account's username. In Identity V3, either
  28. // UserID or a combination of Username and DomainID or DomainName are needed.
  29. Username string `json:"username,omitempty"`
  30. UserID string `json:"id,omitempty"`
  31. Password string `json:"password,omitempty"`
  32. // At most one of DomainID and DomainName must be provided if using Username
  33. // with Identity V3. Otherwise, either are optional.
  34. DomainID string `json:"-"`
  35. DomainName string `json:"name,omitempty"`
  36. // AllowReauth should be set to true if you grant permission for Gophercloud
  37. // to cache your credentials in memory, and to allow Gophercloud to attempt
  38. // to re-authenticate automatically if/when your token expires. If you set
  39. // it to false, it will not cache these settings, but re-authentication will
  40. // not be possible. This setting defaults to false.
  41. AllowReauth bool `json:"-"`
  42. // TokenID allows users to authenticate (possibly as another user) with an
  43. // authentication token ID.
  44. TokenID string `json:"-"`
  45. Scope Scope `json:"-"`
  46. }
  47. // ToTokenV3CreateMap builds a request body from AuthOptions.
  48. func (opts *AuthOptions) ToTokenV3CreateMap(scope map[string]interface{}) (map[string]interface{}, error) {
  49. gophercloudAuthOpts := gophercloud.AuthOptions{
  50. Username: opts.Username,
  51. UserID: opts.UserID,
  52. Password: opts.Password,
  53. DomainID: opts.DomainID,
  54. DomainName: opts.DomainName,
  55. AllowReauth: opts.AllowReauth,
  56. TokenID: opts.TokenID,
  57. }
  58. return gophercloudAuthOpts.ToTokenV3CreateMap(scope)
  59. }
  60. // ToTokenV3CreateMap builds a scope request body from AuthOptions.
  61. func (opts *AuthOptions) ToTokenV3ScopeMap() (map[string]interface{}, error) {
  62. scope := gophercloud.AuthScope(opts.Scope)
  63. gophercloudAuthOpts := gophercloud.AuthOptions{
  64. Scope: &scope,
  65. DomainID: opts.DomainID,
  66. DomainName: opts.DomainName,
  67. }
  68. return gophercloudAuthOpts.ToTokenV3ScopeMap()
  69. }
  70. func (opts *AuthOptions) CanReauth() bool {
  71. return opts.AllowReauth
  72. }
  73. func subjectTokenHeaders(c *gophercloud.ServiceClient, subjectToken string) map[string]string {
  74. return map[string]string{
  75. "X-Subject-Token": subjectToken,
  76. }
  77. }
  78. // Create authenticates and either generates a new token, or changes the Scope
  79. // of an existing token.
  80. func Create(c *gophercloud.ServiceClient, opts AuthOptionsBuilder) (r CreateResult) {
  81. scope, err := opts.ToTokenV3ScopeMap()
  82. if err != nil {
  83. r.Err = err
  84. return
  85. }
  86. b, err := opts.ToTokenV3CreateMap(scope)
  87. if err != nil {
  88. r.Err = err
  89. return
  90. }
  91. resp, err := c.Post(tokenURL(c), b, &r.Body, &gophercloud.RequestOpts{
  92. MoreHeaders: map[string]string{"X-Auth-Token": ""},
  93. })
  94. r.Err = err
  95. if resp != nil {
  96. r.Header = resp.Header
  97. }
  98. return
  99. }
  100. // Get validates and retrieves information about another token.
  101. func Get(c *gophercloud.ServiceClient, token string) (r GetResult) {
  102. resp, err := c.Get(tokenURL(c), &r.Body, &gophercloud.RequestOpts{
  103. MoreHeaders: subjectTokenHeaders(c, token),
  104. OkCodes: []int{200, 203},
  105. })
  106. if resp != nil {
  107. r.Err = err
  108. r.Header = resp.Header
  109. }
  110. return
  111. }
  112. // Validate determines if a specified token is valid or not.
  113. func Validate(c *gophercloud.ServiceClient, token string) (bool, error) {
  114. resp, err := c.Head(tokenURL(c), &gophercloud.RequestOpts{
  115. MoreHeaders: subjectTokenHeaders(c, token),
  116. OkCodes: []int{200, 204, 404},
  117. })
  118. if err != nil {
  119. return false, err
  120. }
  121. return resp.StatusCode == 200 || resp.StatusCode == 204, nil
  122. }
  123. // Revoke immediately makes specified token invalid.
  124. func Revoke(c *gophercloud.ServiceClient, token string) (r RevokeResult) {
  125. _, r.Err = c.Delete(tokenURL(c), &gophercloud.RequestOpts{
  126. MoreHeaders: subjectTokenHeaders(c, token),
  127. })
  128. return
  129. }