code.gitea.io/gitea@v1.21.7/services/auth/group.go (about)

     1  // Copyright 2021 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package auth
     5  
     6  import (
     7  	"net/http"
     8  	"strings"
     9  
    10  	user_model "code.gitea.io/gitea/models/user"
    11  )
    12  
    13  // Ensure the struct implements the interface.
    14  var (
    15  	_ Method = &Group{}
    16  )
    17  
    18  // Group implements the Auth interface with serval Auth.
    19  type Group struct {
    20  	methods []Method
    21  }
    22  
    23  // NewGroup creates a new auth group
    24  func NewGroup(methods ...Method) *Group {
    25  	return &Group{
    26  		methods: methods,
    27  	}
    28  }
    29  
    30  // Add adds a new method to group
    31  func (b *Group) Add(method Method) {
    32  	b.methods = append(b.methods, method)
    33  }
    34  
    35  // Name returns group's methods name
    36  func (b *Group) Name() string {
    37  	names := make([]string, 0, len(b.methods))
    38  	for _, m := range b.methods {
    39  		names = append(names, m.Name())
    40  	}
    41  	return strings.Join(names, ",")
    42  }
    43  
    44  func (b *Group) Verify(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) (*user_model.User, error) {
    45  	// Try to sign in with each of the enabled plugins
    46  	var retErr error
    47  	for _, m := range b.methods {
    48  		user, err := m.Verify(req, w, store, sess)
    49  		if err != nil {
    50  			if retErr == nil {
    51  				retErr = err
    52  			}
    53  			// Try other methods if this one failed.
    54  			// Some methods may share the same protocol to detect if they are matched.
    55  			// For example, OAuth2 and conan.Auth both read token from "Authorization: Bearer <token>" header,
    56  			// If OAuth2 returns error, we should give conan.Auth a chance to try.
    57  			continue
    58  		}
    59  
    60  		// If any method returns a user, we can stop trying.
    61  		// Return the user and ignore any error returned by previous methods.
    62  		if user != nil {
    63  			if store.GetData()["AuthedMethod"] == nil {
    64  				store.GetData()["AuthedMethod"] = m.Name()
    65  			}
    66  			return user, nil
    67  		}
    68  	}
    69  
    70  	// If no method returns a user, return the error returned by the first method.
    71  	return nil, retErr
    72  }