mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 16:40:24 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			123 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			123 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2019 The Go Authors. All rights reserved.
 | 
						|
// Use of this source code is governed by a BSD-style
 | 
						|
// license that can be found in the LICENSE file.
 | 
						|
 | 
						|
package acme
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"encoding/json"
 | 
						|
	"fmt"
 | 
						|
	"net/http"
 | 
						|
)
 | 
						|
 | 
						|
// DeactivateReg permanently disables an existing account associated with c.Key.
 | 
						|
// A deactivated account can no longer request certificate issuance or access
 | 
						|
// resources related to the account, such as orders or authorizations.
 | 
						|
//
 | 
						|
// It works only with RFC8555 compliant CAs.
 | 
						|
func (c *Client) DeactivateReg(ctx context.Context) error {
 | 
						|
	url := string(c.accountKID(ctx))
 | 
						|
	if url == "" {
 | 
						|
		return ErrNoAccount
 | 
						|
	}
 | 
						|
	req := json.RawMessage(`{"status": "deactivated"}`)
 | 
						|
	res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK))
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	res.Body.Close()
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// registerRFC is quivalent to c.Register but for RFC-compliant CAs.
 | 
						|
// It expects c.Discover to have already been called.
 | 
						|
// TODO: Implement externalAccountBinding.
 | 
						|
func (c *Client) registerRFC(ctx context.Context, acct *Account, prompt func(tosURL string) bool) (*Account, error) {
 | 
						|
	c.cacheMu.Lock() // guard c.kid access
 | 
						|
	defer c.cacheMu.Unlock()
 | 
						|
 | 
						|
	req := struct {
 | 
						|
		TermsAgreed bool     `json:"termsOfServiceAgreed,omitempty"`
 | 
						|
		Contact     []string `json:"contact,omitempty"`
 | 
						|
	}{
 | 
						|
		Contact: acct.Contact,
 | 
						|
	}
 | 
						|
	if c.dir.Terms != "" {
 | 
						|
		req.TermsAgreed = prompt(c.dir.Terms)
 | 
						|
	}
 | 
						|
	res, err := c.post(ctx, c.Key, c.dir.RegURL, req, wantStatus(
 | 
						|
		http.StatusOK,      // account with this key already registered
 | 
						|
		http.StatusCreated, // new account created
 | 
						|
	))
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	defer res.Body.Close()
 | 
						|
	a, err := responseAccount(res)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	// Cache Account URL even if we return an error to the caller.
 | 
						|
	// It is by all means a valid and usable "kid" value for future requests.
 | 
						|
	c.kid = keyID(a.URI)
 | 
						|
	if res.StatusCode == http.StatusOK {
 | 
						|
		return nil, ErrAccountAlreadyExists
 | 
						|
	}
 | 
						|
	return a, nil
 | 
						|
}
 | 
						|
 | 
						|
// updateGegRFC is equivalent to c.UpdateReg but for RFC-compliant CAs.
 | 
						|
// It expects c.Discover to have already been called.
 | 
						|
func (c *Client) updateRegRFC(ctx context.Context, a *Account) (*Account, error) {
 | 
						|
	url := string(c.accountKID(ctx))
 | 
						|
	if url == "" {
 | 
						|
		return nil, ErrNoAccount
 | 
						|
	}
 | 
						|
	req := struct {
 | 
						|
		Contact []string `json:"contact,omitempty"`
 | 
						|
	}{
 | 
						|
		Contact: a.Contact,
 | 
						|
	}
 | 
						|
	res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK))
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	defer res.Body.Close()
 | 
						|
	return responseAccount(res)
 | 
						|
}
 | 
						|
 | 
						|
// getGegRFC is equivalent to c.GetReg but for RFC-compliant CAs.
 | 
						|
// It expects c.Discover to have already been called.
 | 
						|
func (c *Client) getRegRFC(ctx context.Context) (*Account, error) {
 | 
						|
	req := json.RawMessage(`{"onlyReturnExisting": true}`)
 | 
						|
	res, err := c.post(ctx, c.Key, c.dir.RegURL, req, wantStatus(http.StatusOK))
 | 
						|
	if e, ok := err.(*Error); ok && e.ProblemType == "urn:ietf:params:acme:error:accountDoesNotExist" {
 | 
						|
		return nil, ErrNoAccount
 | 
						|
	}
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	defer res.Body.Close()
 | 
						|
	return responseAccount(res)
 | 
						|
}
 | 
						|
 | 
						|
func responseAccount(res *http.Response) (*Account, error) {
 | 
						|
	var v struct {
 | 
						|
		Status  string
 | 
						|
		Contact []string
 | 
						|
		Orders  string
 | 
						|
	}
 | 
						|
	if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
 | 
						|
		return nil, fmt.Errorf("acme: invalid response: %v", err)
 | 
						|
	}
 | 
						|
	return &Account{
 | 
						|
		URI:       res.Header.Get("Location"),
 | 
						|
		Status:    v.Status,
 | 
						|
		Contact:   v.Contact,
 | 
						|
		OrdersURL: v.Orders,
 | 
						|
	}, nil
 | 
						|
}
 |