mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-12-22 08:27:06 +00:00
Allow login using multiple forges (#3822)
This commit is contained in:
parent
a26c7a475b
commit
b12d676546
19 changed files with 1182 additions and 97 deletions
|
@ -265,13 +265,6 @@ func run(c *cli.Context) error {
|
|||
}
|
||||
|
||||
func setupEvilGlobals(c *cli.Context, s store.Store) error {
|
||||
// secrets
|
||||
var err error
|
||||
server.Config.Server.JWTSecret, err = setupJWTSecret(s)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not setup jwt secret: %w", err)
|
||||
}
|
||||
|
||||
// services
|
||||
server.Config.Services.Queue = setupQueue(c, s)
|
||||
server.Config.Services.Logs = logging.New()
|
||||
|
@ -319,6 +312,10 @@ func setupEvilGlobals(c *cli.Context, s store.Store) error {
|
|||
server.Config.Pipeline.Proxy.HTTPS = c.String("backend-https-proxy")
|
||||
|
||||
// server configuration
|
||||
server.Config.Server.JWTSecret, err = setupJWTSecret(s)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not setup jwt secret: %w", err)
|
||||
}
|
||||
server.Config.Server.Cert = c.String("server-cert")
|
||||
server.Config.Server.Key = c.String("server-key")
|
||||
server.Config.Server.AgentToken = c.String("agent-secret")
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.34.2
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v4.25.1
|
||||
// source: woodpecker.proto
|
||||
|
||||
|
@ -1312,7 +1312,7 @@ func file_woodpecker_proto_rawDescGZIP() []byte {
|
|||
}
|
||||
|
||||
var file_woodpecker_proto_msgTypes = make([]protoimpl.MessageInfo, 21)
|
||||
var file_woodpecker_proto_goTypes = []any{
|
||||
var file_woodpecker_proto_goTypes = []interface{}{
|
||||
(*StepState)(nil), // 0: proto.StepState
|
||||
(*WorkflowState)(nil), // 1: proto.WorkflowState
|
||||
(*LogEntry)(nil), // 2: proto.LogEntry
|
||||
|
@ -1380,7 +1380,7 @@ func file_woodpecker_proto_init() {
|
|||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_woodpecker_proto_msgTypes[0].Exporter = func(v any, i int) any {
|
||||
file_woodpecker_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*StepState); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
|
@ -1392,7 +1392,7 @@ func file_woodpecker_proto_init() {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
file_woodpecker_proto_msgTypes[1].Exporter = func(v any, i int) any {
|
||||
file_woodpecker_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*WorkflowState); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
|
@ -1404,7 +1404,7 @@ func file_woodpecker_proto_init() {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
file_woodpecker_proto_msgTypes[2].Exporter = func(v any, i int) any {
|
||||
file_woodpecker_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*LogEntry); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
|
@ -1416,7 +1416,7 @@ func file_woodpecker_proto_init() {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
file_woodpecker_proto_msgTypes[3].Exporter = func(v any, i int) any {
|
||||
file_woodpecker_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Filter); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
|
@ -1428,7 +1428,7 @@ func file_woodpecker_proto_init() {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
file_woodpecker_proto_msgTypes[4].Exporter = func(v any, i int) any {
|
||||
file_woodpecker_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Workflow); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
|
@ -1440,7 +1440,7 @@ func file_woodpecker_proto_init() {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
file_woodpecker_proto_msgTypes[5].Exporter = func(v any, i int) any {
|
||||
file_woodpecker_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*NextRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
|
@ -1452,7 +1452,7 @@ func file_woodpecker_proto_init() {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
file_woodpecker_proto_msgTypes[6].Exporter = func(v any, i int) any {
|
||||
file_woodpecker_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*InitRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
|
@ -1464,7 +1464,7 @@ func file_woodpecker_proto_init() {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
file_woodpecker_proto_msgTypes[7].Exporter = func(v any, i int) any {
|
||||
file_woodpecker_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*WaitRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
|
@ -1476,7 +1476,7 @@ func file_woodpecker_proto_init() {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
file_woodpecker_proto_msgTypes[8].Exporter = func(v any, i int) any {
|
||||
file_woodpecker_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*DoneRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
|
@ -1488,7 +1488,7 @@ func file_woodpecker_proto_init() {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
file_woodpecker_proto_msgTypes[9].Exporter = func(v any, i int) any {
|
||||
file_woodpecker_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ExtendRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
|
@ -1500,7 +1500,7 @@ func file_woodpecker_proto_init() {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
file_woodpecker_proto_msgTypes[10].Exporter = func(v any, i int) any {
|
||||
file_woodpecker_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*UpdateRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
|
@ -1512,7 +1512,7 @@ func file_woodpecker_proto_init() {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
file_woodpecker_proto_msgTypes[11].Exporter = func(v any, i int) any {
|
||||
file_woodpecker_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*LogRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
|
@ -1524,7 +1524,7 @@ func file_woodpecker_proto_init() {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
file_woodpecker_proto_msgTypes[12].Exporter = func(v any, i int) any {
|
||||
file_woodpecker_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Empty); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
|
@ -1536,7 +1536,7 @@ func file_woodpecker_proto_init() {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
file_woodpecker_proto_msgTypes[13].Exporter = func(v any, i int) any {
|
||||
file_woodpecker_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ReportHealthRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
|
@ -1548,7 +1548,7 @@ func file_woodpecker_proto_init() {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
file_woodpecker_proto_msgTypes[14].Exporter = func(v any, i int) any {
|
||||
file_woodpecker_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*RegisterAgentRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
|
@ -1560,7 +1560,7 @@ func file_woodpecker_proto_init() {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
file_woodpecker_proto_msgTypes[15].Exporter = func(v any, i int) any {
|
||||
file_woodpecker_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*VersionResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
|
@ -1572,7 +1572,7 @@ func file_woodpecker_proto_init() {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
file_woodpecker_proto_msgTypes[16].Exporter = func(v any, i int) any {
|
||||
file_woodpecker_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*NextResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
|
@ -1584,7 +1584,7 @@ func file_woodpecker_proto_init() {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
file_woodpecker_proto_msgTypes[17].Exporter = func(v any, i int) any {
|
||||
file_woodpecker_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*RegisterAgentResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
|
@ -1596,7 +1596,7 @@ func file_woodpecker_proto_init() {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
file_woodpecker_proto_msgTypes[18].Exporter = func(v any, i int) any {
|
||||
file_woodpecker_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*AuthRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
|
@ -1608,7 +1608,7 @@ func file_woodpecker_proto_init() {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
file_woodpecker_proto_msgTypes[19].Exporter = func(v any, i int) any {
|
||||
file_woodpecker_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*AuthResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
|
|
|
@ -104,18 +104,47 @@ func BlockTilQueueHasRunningItem(c *gin.Context) {
|
|||
func PostHook(c *gin.Context) {
|
||||
_store := store.FromContext(c)
|
||||
|
||||
_forge, err := server.Config.Services.Manager.ForgeByID(1) // TODO: get the forge for the specific repo somehow
|
||||
//
|
||||
// 1. Check if the webhook is valid and authorized
|
||||
//
|
||||
|
||||
var repo *model.Repo
|
||||
|
||||
_, err := token.ParseRequest([]token.Type{token.HookToken}, c.Request, func(t *token.Token) (string, error) {
|
||||
var err error
|
||||
repo, err = getRepoFromToken(_store, t)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Cannot get main forge")
|
||||
return "", err
|
||||
}
|
||||
|
||||
return repo.Hash, nil
|
||||
})
|
||||
if err != nil {
|
||||
msg := "failure to parse token from hook"
|
||||
log.Error().Err(err).Msg(msg)
|
||||
c.String(http.StatusBadRequest, msg)
|
||||
return
|
||||
}
|
||||
|
||||
if repo == nil {
|
||||
msg := "failure to get repo from token"
|
||||
log.Error().Msg(msg)
|
||||
c.String(http.StatusBadRequest, msg)
|
||||
return
|
||||
}
|
||||
|
||||
_forge, err := server.Config.Services.Manager.ForgeFromRepo(repo)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Int64("repo-id", repo.ID).Msgf("Cannot get forge with id: %d", repo.ForgeID)
|
||||
c.AbortWithStatus(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
//
|
||||
// 1. Parse webhook
|
||||
// 2. Parse the webhook data
|
||||
//
|
||||
|
||||
tmpRepo, tmpPipeline, err := _forge.Hook(c, c.Request)
|
||||
repoFromForge, pipelineFromForge, err := _forge.Hook(c, c.Request)
|
||||
if err != nil {
|
||||
if errors.Is(err, &types.ErrIgnoreEvent{}) {
|
||||
msg := fmt.Sprintf("forge driver: %s", err)
|
||||
|
@ -130,13 +159,13 @@ func PostHook(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
if tmpPipeline == nil {
|
||||
if pipelineFromForge == nil {
|
||||
msg := "ignoring hook: hook parsing resulted in empty pipeline"
|
||||
log.Debug().Msg(msg)
|
||||
c.String(http.StatusOK, msg)
|
||||
return
|
||||
}
|
||||
if tmpRepo == nil {
|
||||
if repoFromForge == nil {
|
||||
msg := "failure to ascertain repo from hook"
|
||||
log.Debug().Msg(msg)
|
||||
c.String(http.StatusBadRequest, msg)
|
||||
|
@ -144,21 +173,24 @@ func PostHook(c *gin.Context) {
|
|||
}
|
||||
|
||||
//
|
||||
// 2. Get related repo from store and take repo renaming into account
|
||||
// 3. Check the repo from the token is matching the repo returned by the forge
|
||||
//
|
||||
|
||||
repo, err := _store.GetRepoNameFallback(tmpRepo.ForgeRemoteID, tmpRepo.FullName)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msgf("failure to get repo %s from store", tmpRepo.FullName)
|
||||
handleDBError(c, err)
|
||||
if repo.ForgeRemoteID != repoFromForge.ForgeRemoteID {
|
||||
log.Warn().Msgf("ignoring hook: repo %s does not match the repo from the token", repo.FullName)
|
||||
c.String(http.StatusBadRequest, "failure to parse token from hook")
|
||||
return
|
||||
}
|
||||
|
||||
//
|
||||
// 4. Check if the repo is active and has an owner
|
||||
//
|
||||
|
||||
if !repo.IsActive {
|
||||
log.Debug().Msgf("ignoring hook: repo %s is inactive", tmpRepo.FullName)
|
||||
log.Debug().Msgf("ignoring hook: repo %s is inactive", repoFromForge.FullName)
|
||||
c.Status(http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
currentRepoFullName := repo.FullName
|
||||
|
||||
if repo.UserID == 0 {
|
||||
log.Warn().Msgf("ignoring hook. repo %s has no owner.", repo.FullName)
|
||||
|
@ -174,44 +206,10 @@ func PostHook(c *gin.Context) {
|
|||
forge.Refresh(c, _forge, _store, user)
|
||||
|
||||
//
|
||||
// 3. Check if the webhook is a valid and authorized one
|
||||
// 4. Update the repo
|
||||
//
|
||||
|
||||
// get the token and verify the hook is authorized
|
||||
parsedToken, err := token.ParseRequest([]token.Type{token.HookToken}, c.Request, func(_ *token.Token) (string, error) {
|
||||
return repo.Hash, nil
|
||||
})
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("failure to parse token from hook for %s", repo.FullName)
|
||||
log.Error().Err(err).Msg(msg)
|
||||
c.String(http.StatusBadRequest, msg)
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: remove fallback for text full name in next major release
|
||||
verifiedKey := parsedToken.Get("repo-id") == strconv.FormatInt(repo.ID, 10) || parsedToken.Get("text") == currentRepoFullName
|
||||
if !verifiedKey {
|
||||
verifiedKey, err = _store.HasRedirectionForRepo(repo.ID, repo.FullName)
|
||||
if err != nil {
|
||||
msg := "failure to verify token from hook. Could not check for redirections of the repo"
|
||||
log.Error().Err(err).Msg(msg)
|
||||
c.String(http.StatusInternalServerError, msg)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if !verifiedKey {
|
||||
msg := fmt.Sprintf("failure to verify token from hook. Expected %s, got %s", repo.FullName, parsedToken.Get("text"))
|
||||
log.Debug().Msg(msg)
|
||||
c.String(http.StatusForbidden, msg)
|
||||
return
|
||||
}
|
||||
|
||||
//
|
||||
// 4. Update repo
|
||||
//
|
||||
|
||||
if currentRepoFullName != tmpRepo.FullName {
|
||||
if repo.FullName != repoFromForge.FullName {
|
||||
// create a redirection
|
||||
err = _store.CreateRedirection(&model.Redirection{RepoID: repo.ID, FullName: repo.FullName})
|
||||
if err != nil {
|
||||
|
@ -220,7 +218,7 @@ func PostHook(c *gin.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
repo.Update(tmpRepo)
|
||||
repo.Update(repoFromForge)
|
||||
err = _store.UpdateRepo(repo)
|
||||
if err != nil {
|
||||
c.String(http.StatusInternalServerError, err.Error())
|
||||
|
@ -231,7 +229,7 @@ func PostHook(c *gin.Context) {
|
|||
// 5. Check if pull requests are allowed for this repo
|
||||
//
|
||||
|
||||
if (tmpPipeline.Event == model.EventPull || tmpPipeline.Event == model.EventPullClosed) && !repo.AllowPull {
|
||||
if (pipelineFromForge.Event == model.EventPull || pipelineFromForge.Event == model.EventPullClosed) && !repo.AllowPull {
|
||||
log.Debug().Str("repo", repo.FullName).Msg("ignoring hook: pull requests are disabled for this repo in woodpecker")
|
||||
c.Status(http.StatusNoContent)
|
||||
return
|
||||
|
@ -241,10 +239,22 @@ func PostHook(c *gin.Context) {
|
|||
// 6. Finally create a pipeline
|
||||
//
|
||||
|
||||
pl, err := pipeline.Create(c, _store, repo, tmpPipeline)
|
||||
pl, err := pipeline.Create(c, _store, repo, pipelineFromForge)
|
||||
if err != nil {
|
||||
handlePipelineErr(c, err)
|
||||
} else {
|
||||
c.JSON(http.StatusOK, pl)
|
||||
}
|
||||
}
|
||||
|
||||
func getRepoFromToken(store store.Store, t *token.Token) (*model.Repo, error) {
|
||||
// try to get the repo by the repo-id
|
||||
repoID, err := strconv.ParseInt(t.Get("repo-id"), 10, 64)
|
||||
if err == nil {
|
||||
return store.GetRepo(repoID)
|
||||
}
|
||||
|
||||
// try to get the repo by the repo name or by its redirection
|
||||
repoName := t.Get("text")
|
||||
return store.GetRepoName(repoName)
|
||||
}
|
||||
|
|
104
server/api/hook_test.go
Normal file
104
server/api/hook_test.go
Normal file
|
@ -0,0 +1,104 @@
|
|||
package api_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/franela/goblin"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
|
||||
"go.woodpecker-ci.org/woodpecker/v2/server"
|
||||
"go.woodpecker-ci.org/woodpecker/v2/server/api"
|
||||
mocks_forge "go.woodpecker-ci.org/woodpecker/v2/server/forge/mocks"
|
||||
"go.woodpecker-ci.org/woodpecker/v2/server/model"
|
||||
mocks_config_service "go.woodpecker-ci.org/woodpecker/v2/server/services/config/mocks"
|
||||
mocks_services "go.woodpecker-ci.org/woodpecker/v2/server/services/mocks"
|
||||
"go.woodpecker-ci.org/woodpecker/v2/server/services/permissions"
|
||||
mocks_registry_service "go.woodpecker-ci.org/woodpecker/v2/server/services/registry/mocks"
|
||||
mocks_secret_service "go.woodpecker-ci.org/woodpecker/v2/server/services/secret/mocks"
|
||||
mocks_store "go.woodpecker-ci.org/woodpecker/v2/server/store/mocks"
|
||||
"go.woodpecker-ci.org/woodpecker/v2/shared/token"
|
||||
)
|
||||
|
||||
func TestHook(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
g := goblin.Goblin(t)
|
||||
g.Describe("Hook", func() {
|
||||
g.It("should handle a correct webhook payload", func() {
|
||||
_manager := mocks_services.NewManager(t)
|
||||
_forge := mocks_forge.NewForge(t)
|
||||
_store := mocks_store.NewStore(t)
|
||||
_configService := mocks_config_service.NewService(t)
|
||||
_secretService := mocks_secret_service.NewService(t)
|
||||
_registryService := mocks_registry_service.NewService(t)
|
||||
server.Config.Services.Manager = _manager
|
||||
server.Config.Permissions.Open = true
|
||||
server.Config.Permissions.Orgs = permissions.NewOrgs(nil)
|
||||
server.Config.Permissions.Admins = permissions.NewAdmins(nil)
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
c.Set("store", _store)
|
||||
user := &model.User{
|
||||
ID: 123,
|
||||
}
|
||||
repo := &model.Repo{
|
||||
ID: 123,
|
||||
ForgeRemoteID: "123",
|
||||
Owner: "owner",
|
||||
Name: "name",
|
||||
IsActive: true,
|
||||
UserID: user.ID,
|
||||
Hash: "secret-123-this-is-a-secret",
|
||||
}
|
||||
pipeline := &model.Pipeline{
|
||||
ID: 123,
|
||||
RepoID: repo.ID,
|
||||
Event: model.EventPush,
|
||||
}
|
||||
|
||||
repoToken := token.New(token.HookToken)
|
||||
repoToken.Set("repo-id", fmt.Sprintf("%d", repo.ID))
|
||||
signedToken, err := repoToken.Sign("secret-123-this-is-a-secret")
|
||||
if err != nil {
|
||||
g.Fail(err)
|
||||
}
|
||||
|
||||
header := http.Header{}
|
||||
header.Set("Authorization", fmt.Sprintf("Bearer %s", signedToken))
|
||||
c.Request = &http.Request{
|
||||
Header: header,
|
||||
URL: &url.URL{
|
||||
Scheme: "https",
|
||||
},
|
||||
}
|
||||
|
||||
_manager.On("ForgeFromRepo", repo).Return(_forge, nil)
|
||||
_forge.On("Hook", mock.Anything, mock.Anything).Return(repo, pipeline, nil)
|
||||
_store.On("GetRepo", repo.ID).Return(repo, nil)
|
||||
_store.On("GetUser", user.ID).Return(user, nil)
|
||||
_store.On("UpdateRepo", repo).Return(nil)
|
||||
_store.On("CreatePipeline", mock.Anything).Return(nil)
|
||||
_manager.On("ConfigServiceFromRepo", repo).Return(_configService)
|
||||
_configService.On("Fetch", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, nil)
|
||||
_forge.On("Netrc", mock.Anything, mock.Anything).Return(&model.Netrc{}, nil)
|
||||
_store.On("GetPipelineLastBefore", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil)
|
||||
_manager.On("SecretServiceFromRepo", repo).Return(_secretService)
|
||||
_secretService.On("SecretListPipeline", repo, mock.Anything, mock.Anything).Return(nil, nil)
|
||||
_manager.On("RegistryServiceFromRepo", repo).Return(_registryService)
|
||||
_registryService.On("RegistryListPipeline", repo, mock.Anything).Return(nil, nil)
|
||||
_manager.On("EnvironmentService").Return(nil)
|
||||
_store.On("DeletePipeline", mock.Anything).Return(nil)
|
||||
|
||||
api.PostHook(c)
|
||||
|
||||
assert.Equal(g, http.StatusNoContent, c.Writer.Status())
|
||||
assert.Equal(g, "true", w.Header().Get("Pipeline-Filtered"))
|
||||
})
|
||||
})
|
||||
}
|
|
@ -62,10 +62,10 @@ func HandleAuth(c *gin.Context) {
|
|||
code := c.Request.FormValue("code")
|
||||
state := c.Request.FormValue("state")
|
||||
isCallback := code != "" && state != ""
|
||||
forgeID := int64(1) // TODO: replace with forge id when multiple forges are supported
|
||||
var forgeID int64
|
||||
|
||||
if isCallback { // validate the state token
|
||||
_, err := token.Parse([]token.Type{token.OAuthStateToken}, state, func(_ *token.Token) (string, error) {
|
||||
stateToken, err := token.Parse([]token.Type{token.OAuthStateToken}, state, func(_ *token.Token) (string, error) {
|
||||
return server.Config.Server.JWTSecret, nil
|
||||
})
|
||||
if err != nil {
|
||||
|
@ -73,8 +73,29 @@ func HandleAuth(c *gin.Context) {
|
|||
c.Redirect(http.StatusSeeOther, server.Config.Server.RootPath+"/login?error=invalid_state")
|
||||
return
|
||||
}
|
||||
|
||||
_forgeID := stateToken.Get("forge-id")
|
||||
forgeID, err = strconv.ParseInt(_forgeID, 10, 64)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("forge-id of state token invalid")
|
||||
c.Redirect(http.StatusSeeOther, server.Config.Server.RootPath+"/login?error=invalid_state")
|
||||
return
|
||||
}
|
||||
} else { // only generate a state token if not a callback
|
||||
var err error
|
||||
|
||||
_forgeID := c.Request.FormValue("forge_id")
|
||||
if _forgeID == "" {
|
||||
forgeID = 1 // fallback to main forge
|
||||
} else {
|
||||
forgeID, err = strconv.ParseInt(_forgeID, 10, 64)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("forge-id of state token invalid")
|
||||
c.Redirect(http.StatusSeeOther, server.Config.Server.RootPath+"/login?error=invalid_state")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
jwtSecret := server.Config.Server.JWTSecret
|
||||
exp := time.Now().Add(stateTokenDuration).Unix()
|
||||
stateToken := token.New(token.OAuthStateToken)
|
||||
|
@ -208,6 +229,7 @@ func HandleAuth(c *gin.Context) {
|
|||
user.Secret = userFromForge.Secret
|
||||
user.Email = userFromForge.Email
|
||||
user.Avatar = userFromForge.Avatar
|
||||
user.ForgeID = forgeID
|
||||
user.ForgeRemoteID = userFromForge.ForgeRemoteID
|
||||
user.Login = userFromForge.Login
|
||||
user.Admin = user.Admin || server.Config.Permissions.Admins.IsAdmin(userFromForge)
|
||||
|
@ -280,7 +302,7 @@ func GetLogout(c *gin.Context) {
|
|||
func DeprecatedGetLoginToken(c *gin.Context) {
|
||||
_store := store.FromContext(c)
|
||||
|
||||
_forge, err := server.Config.Services.Manager.ForgeByID(1) // TODO: get selected forge from auth request
|
||||
_forge, err := server.Config.Services.Manager.ForgeByID(1)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Cannot get main forge")
|
||||
c.AbortWithStatus(http.StatusInternalServerError)
|
||||
|
|
63
server/services/config/mocks/service.go
Normal file
63
server/services/config/mocks/service.go
Normal file
|
@ -0,0 +1,63 @@
|
|||
// Code generated by mockery. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
forge "go.woodpecker-ci.org/woodpecker/v2/server/forge"
|
||||
|
||||
model "go.woodpecker-ci.org/woodpecker/v2/server/model"
|
||||
|
||||
types "go.woodpecker-ci.org/woodpecker/v2/server/forge/types"
|
||||
)
|
||||
|
||||
// Service is an autogenerated mock type for the Service type
|
||||
type Service struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// Fetch provides a mock function with given fields: ctx, _a1, user, repo, pipeline, oldConfigData, restart
|
||||
func (_m *Service) Fetch(ctx context.Context, _a1 forge.Forge, user *model.User, repo *model.Repo, pipeline *model.Pipeline, oldConfigData []*types.FileMeta, restart bool) ([]*types.FileMeta, error) {
|
||||
ret := _m.Called(ctx, _a1, user, repo, pipeline, oldConfigData, restart)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Fetch")
|
||||
}
|
||||
|
||||
var r0 []*types.FileMeta
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, forge.Forge, *model.User, *model.Repo, *model.Pipeline, []*types.FileMeta, bool) ([]*types.FileMeta, error)); ok {
|
||||
return rf(ctx, _a1, user, repo, pipeline, oldConfigData, restart)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, forge.Forge, *model.User, *model.Repo, *model.Pipeline, []*types.FileMeta, bool) []*types.FileMeta); ok {
|
||||
r0 = rf(ctx, _a1, user, repo, pipeline, oldConfigData, restart)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*types.FileMeta)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, forge.Forge, *model.User, *model.Repo, *model.Pipeline, []*types.FileMeta, bool) error); ok {
|
||||
r1 = rf(ctx, _a1, user, repo, pipeline, oldConfigData, restart)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// NewService creates a new instance of Service. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
// The first argument is typically a *testing.T value.
|
||||
func NewService(t interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}) *Service {
|
||||
mock := &Service{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
|
@ -22,6 +22,8 @@ import (
|
|||
"go.woodpecker-ci.org/woodpecker/v2/server/model"
|
||||
)
|
||||
|
||||
//go:generate mockery --name Service --output mocks --case underscore
|
||||
|
||||
type Service interface {
|
||||
Fetch(ctx context.Context, forge forge.Forge, user *model.User, repo *model.Repo, pipeline *model.Pipeline, oldConfigData []*types.FileMeta, restart bool) (configData []*types.FileMeta, err error)
|
||||
}
|
||||
|
|
57
server/services/environment/mocks/service.go
Normal file
57
server/services/environment/mocks/service.go
Normal file
|
@ -0,0 +1,57 @@
|
|||
// Code generated by mockery. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
model "go.woodpecker-ci.org/woodpecker/v2/server/model"
|
||||
)
|
||||
|
||||
// Service is an autogenerated mock type for the Service type
|
||||
type Service struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// EnvironList provides a mock function with given fields: _a0
|
||||
func (_m *Service) EnvironList(_a0 *model.Repo) ([]*model.Environ, error) {
|
||||
ret := _m.Called(_a0)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for EnvironList")
|
||||
}
|
||||
|
||||
var r0 []*model.Environ
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(*model.Repo) ([]*model.Environ, error)); ok {
|
||||
return rf(_a0)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(*model.Repo) []*model.Environ); ok {
|
||||
r0 = rf(_a0)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*model.Environ)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(*model.Repo) error); ok {
|
||||
r1 = rf(_a0)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// NewService creates a new instance of Service. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
// The first argument is typically a *testing.T value.
|
||||
func NewService(t interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}) *Service {
|
||||
mock := &Service{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
|
@ -16,6 +16,8 @@ package environment
|
|||
|
||||
import "go.woodpecker-ci.org/woodpecker/v2/server/model"
|
||||
|
||||
//go:generate mockery --name Service --output mocks --case underscore
|
||||
|
||||
// Service defines a service for managing environment variables.
|
||||
type Service interface {
|
||||
EnvironList(*model.Repo) ([]*model.Environ, error)
|
||||
|
|
|
@ -46,7 +46,7 @@ type Manager interface {
|
|||
EnvironmentService() environment.Service
|
||||
ForgeFromRepo(repo *model.Repo) (forge.Forge, error)
|
||||
ForgeFromUser(user *model.User) (forge.Forge, error)
|
||||
ForgeByID(id int64) (forge.Forge, error)
|
||||
ForgeByID(forgeID int64) (forge.Forge, error)
|
||||
}
|
||||
|
||||
type manager struct {
|
||||
|
|
|
@ -68,9 +68,9 @@ func (_m *Manager) EnvironmentService() environment.Service {
|
|||
return r0
|
||||
}
|
||||
|
||||
// ForgeByID provides a mock function with given fields: id
|
||||
func (_m *Manager) ForgeByID(id int64) (forge.Forge, error) {
|
||||
ret := _m.Called(id)
|
||||
// ForgeByID provides a mock function with given fields: forgeID
|
||||
func (_m *Manager) ForgeByID(forgeID int64) (forge.Forge, error) {
|
||||
ret := _m.Called(forgeID)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ForgeByID")
|
||||
|
@ -79,10 +79,10 @@ func (_m *Manager) ForgeByID(id int64) (forge.Forge, error) {
|
|||
var r0 forge.Forge
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(int64) (forge.Forge, error)); ok {
|
||||
return rf(id)
|
||||
return rf(forgeID)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(int64) forge.Forge); ok {
|
||||
r0 = rf(id)
|
||||
r0 = rf(forgeID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(forge.Forge)
|
||||
|
@ -90,7 +90,7 @@ func (_m *Manager) ForgeByID(id int64) (forge.Forge, error) {
|
|||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(int64) error); ok {
|
||||
r1 = rf(id)
|
||||
r1 = rf(forgeID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
|
399
server/services/registry/mocks/service.go
Normal file
399
server/services/registry/mocks/service.go
Normal file
|
@ -0,0 +1,399 @@
|
|||
// Code generated by mockery. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
model "go.woodpecker-ci.org/woodpecker/v2/server/model"
|
||||
)
|
||||
|
||||
// Service is an autogenerated mock type for the Service type
|
||||
type Service struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// GlobalRegistryCreate provides a mock function with given fields: _a0
|
||||
func (_m *Service) GlobalRegistryCreate(_a0 *model.Registry) error {
|
||||
ret := _m.Called(_a0)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GlobalRegistryCreate")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(*model.Registry) error); ok {
|
||||
r0 = rf(_a0)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// GlobalRegistryDelete provides a mock function with given fields: _a0
|
||||
func (_m *Service) GlobalRegistryDelete(_a0 string) error {
|
||||
ret := _m.Called(_a0)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GlobalRegistryDelete")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(string) error); ok {
|
||||
r0 = rf(_a0)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// GlobalRegistryFind provides a mock function with given fields: _a0
|
||||
func (_m *Service) GlobalRegistryFind(_a0 string) (*model.Registry, error) {
|
||||
ret := _m.Called(_a0)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GlobalRegistryFind")
|
||||
}
|
||||
|
||||
var r0 *model.Registry
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(string) (*model.Registry, error)); ok {
|
||||
return rf(_a0)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(string) *model.Registry); ok {
|
||||
r0 = rf(_a0)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*model.Registry)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(string) error); ok {
|
||||
r1 = rf(_a0)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GlobalRegistryList provides a mock function with given fields: _a0
|
||||
func (_m *Service) GlobalRegistryList(_a0 *model.ListOptions) ([]*model.Registry, error) {
|
||||
ret := _m.Called(_a0)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GlobalRegistryList")
|
||||
}
|
||||
|
||||
var r0 []*model.Registry
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(*model.ListOptions) ([]*model.Registry, error)); ok {
|
||||
return rf(_a0)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(*model.ListOptions) []*model.Registry); ok {
|
||||
r0 = rf(_a0)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*model.Registry)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(*model.ListOptions) error); ok {
|
||||
r1 = rf(_a0)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GlobalRegistryUpdate provides a mock function with given fields: _a0
|
||||
func (_m *Service) GlobalRegistryUpdate(_a0 *model.Registry) error {
|
||||
ret := _m.Called(_a0)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GlobalRegistryUpdate")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(*model.Registry) error); ok {
|
||||
r0 = rf(_a0)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// OrgRegistryCreate provides a mock function with given fields: _a0, _a1
|
||||
func (_m *Service) OrgRegistryCreate(_a0 int64, _a1 *model.Registry) error {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for OrgRegistryCreate")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(int64, *model.Registry) error); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// OrgRegistryDelete provides a mock function with given fields: _a0, _a1
|
||||
func (_m *Service) OrgRegistryDelete(_a0 int64, _a1 string) error {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for OrgRegistryDelete")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(int64, string) error); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// OrgRegistryFind provides a mock function with given fields: _a0, _a1
|
||||
func (_m *Service) OrgRegistryFind(_a0 int64, _a1 string) (*model.Registry, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for OrgRegistryFind")
|
||||
}
|
||||
|
||||
var r0 *model.Registry
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(int64, string) (*model.Registry, error)); ok {
|
||||
return rf(_a0, _a1)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(int64, string) *model.Registry); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*model.Registry)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(int64, string) error); ok {
|
||||
r1 = rf(_a0, _a1)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// OrgRegistryList provides a mock function with given fields: _a0, _a1
|
||||
func (_m *Service) OrgRegistryList(_a0 int64, _a1 *model.ListOptions) ([]*model.Registry, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for OrgRegistryList")
|
||||
}
|
||||
|
||||
var r0 []*model.Registry
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(int64, *model.ListOptions) ([]*model.Registry, error)); ok {
|
||||
return rf(_a0, _a1)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(int64, *model.ListOptions) []*model.Registry); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*model.Registry)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(int64, *model.ListOptions) error); ok {
|
||||
r1 = rf(_a0, _a1)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// OrgRegistryUpdate provides a mock function with given fields: _a0, _a1
|
||||
func (_m *Service) OrgRegistryUpdate(_a0 int64, _a1 *model.Registry) error {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for OrgRegistryUpdate")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(int64, *model.Registry) error); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// RegistryCreate provides a mock function with given fields: _a0, _a1
|
||||
func (_m *Service) RegistryCreate(_a0 *model.Repo, _a1 *model.Registry) error {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RegistryCreate")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(*model.Repo, *model.Registry) error); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// RegistryDelete provides a mock function with given fields: _a0, _a1
|
||||
func (_m *Service) RegistryDelete(_a0 *model.Repo, _a1 string) error {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RegistryDelete")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(*model.Repo, string) error); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// RegistryFind provides a mock function with given fields: _a0, _a1
|
||||
func (_m *Service) RegistryFind(_a0 *model.Repo, _a1 string) (*model.Registry, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RegistryFind")
|
||||
}
|
||||
|
||||
var r0 *model.Registry
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(*model.Repo, string) (*model.Registry, error)); ok {
|
||||
return rf(_a0, _a1)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(*model.Repo, string) *model.Registry); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*model.Registry)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(*model.Repo, string) error); ok {
|
||||
r1 = rf(_a0, _a1)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// RegistryList provides a mock function with given fields: _a0, _a1
|
||||
func (_m *Service) RegistryList(_a0 *model.Repo, _a1 *model.ListOptions) ([]*model.Registry, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RegistryList")
|
||||
}
|
||||
|
||||
var r0 []*model.Registry
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(*model.Repo, *model.ListOptions) ([]*model.Registry, error)); ok {
|
||||
return rf(_a0, _a1)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(*model.Repo, *model.ListOptions) []*model.Registry); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*model.Registry)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(*model.Repo, *model.ListOptions) error); ok {
|
||||
r1 = rf(_a0, _a1)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// RegistryListPipeline provides a mock function with given fields: _a0, _a1
|
||||
func (_m *Service) RegistryListPipeline(_a0 *model.Repo, _a1 *model.Pipeline) ([]*model.Registry, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RegistryListPipeline")
|
||||
}
|
||||
|
||||
var r0 []*model.Registry
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(*model.Repo, *model.Pipeline) ([]*model.Registry, error)); ok {
|
||||
return rf(_a0, _a1)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(*model.Repo, *model.Pipeline) []*model.Registry); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*model.Registry)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(*model.Repo, *model.Pipeline) error); ok {
|
||||
r1 = rf(_a0, _a1)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// RegistryUpdate provides a mock function with given fields: _a0, _a1
|
||||
func (_m *Service) RegistryUpdate(_a0 *model.Repo, _a1 *model.Registry) error {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RegistryUpdate")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(*model.Repo, *model.Registry) error); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// NewService creates a new instance of Service. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
// The first argument is typically a *testing.T value.
|
||||
func NewService(t interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}) *Service {
|
||||
mock := &Service{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
|
@ -16,6 +16,8 @@ package registry
|
|||
|
||||
import "go.woodpecker-ci.org/woodpecker/v2/server/model"
|
||||
|
||||
//go:generate mockery --name Service --output mocks --case underscore
|
||||
|
||||
// Service defines a service for managing registries.
|
||||
type Service interface {
|
||||
RegistryListPipeline(*model.Repo, *model.Pipeline) ([]*model.Registry, error)
|
||||
|
|
399
server/services/secret/mocks/service.go
Normal file
399
server/services/secret/mocks/service.go
Normal file
|
@ -0,0 +1,399 @@
|
|||
// Code generated by mockery. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
model "go.woodpecker-ci.org/woodpecker/v2/server/model"
|
||||
)
|
||||
|
||||
// Service is an autogenerated mock type for the Service type
|
||||
type Service struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// GlobalSecretCreate provides a mock function with given fields: _a0
|
||||
func (_m *Service) GlobalSecretCreate(_a0 *model.Secret) error {
|
||||
ret := _m.Called(_a0)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GlobalSecretCreate")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(*model.Secret) error); ok {
|
||||
r0 = rf(_a0)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// GlobalSecretDelete provides a mock function with given fields: _a0
|
||||
func (_m *Service) GlobalSecretDelete(_a0 string) error {
|
||||
ret := _m.Called(_a0)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GlobalSecretDelete")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(string) error); ok {
|
||||
r0 = rf(_a0)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// GlobalSecretFind provides a mock function with given fields: _a0
|
||||
func (_m *Service) GlobalSecretFind(_a0 string) (*model.Secret, error) {
|
||||
ret := _m.Called(_a0)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GlobalSecretFind")
|
||||
}
|
||||
|
||||
var r0 *model.Secret
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(string) (*model.Secret, error)); ok {
|
||||
return rf(_a0)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(string) *model.Secret); ok {
|
||||
r0 = rf(_a0)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*model.Secret)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(string) error); ok {
|
||||
r1 = rf(_a0)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GlobalSecretList provides a mock function with given fields: _a0
|
||||
func (_m *Service) GlobalSecretList(_a0 *model.ListOptions) ([]*model.Secret, error) {
|
||||
ret := _m.Called(_a0)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GlobalSecretList")
|
||||
}
|
||||
|
||||
var r0 []*model.Secret
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(*model.ListOptions) ([]*model.Secret, error)); ok {
|
||||
return rf(_a0)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(*model.ListOptions) []*model.Secret); ok {
|
||||
r0 = rf(_a0)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*model.Secret)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(*model.ListOptions) error); ok {
|
||||
r1 = rf(_a0)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GlobalSecretUpdate provides a mock function with given fields: _a0
|
||||
func (_m *Service) GlobalSecretUpdate(_a0 *model.Secret) error {
|
||||
ret := _m.Called(_a0)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GlobalSecretUpdate")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(*model.Secret) error); ok {
|
||||
r0 = rf(_a0)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// OrgSecretCreate provides a mock function with given fields: _a0, _a1
|
||||
func (_m *Service) OrgSecretCreate(_a0 int64, _a1 *model.Secret) error {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for OrgSecretCreate")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(int64, *model.Secret) error); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// OrgSecretDelete provides a mock function with given fields: _a0, _a1
|
||||
func (_m *Service) OrgSecretDelete(_a0 int64, _a1 string) error {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for OrgSecretDelete")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(int64, string) error); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// OrgSecretFind provides a mock function with given fields: _a0, _a1
|
||||
func (_m *Service) OrgSecretFind(_a0 int64, _a1 string) (*model.Secret, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for OrgSecretFind")
|
||||
}
|
||||
|
||||
var r0 *model.Secret
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(int64, string) (*model.Secret, error)); ok {
|
||||
return rf(_a0, _a1)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(int64, string) *model.Secret); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*model.Secret)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(int64, string) error); ok {
|
||||
r1 = rf(_a0, _a1)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// OrgSecretList provides a mock function with given fields: _a0, _a1
|
||||
func (_m *Service) OrgSecretList(_a0 int64, _a1 *model.ListOptions) ([]*model.Secret, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for OrgSecretList")
|
||||
}
|
||||
|
||||
var r0 []*model.Secret
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(int64, *model.ListOptions) ([]*model.Secret, error)); ok {
|
||||
return rf(_a0, _a1)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(int64, *model.ListOptions) []*model.Secret); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*model.Secret)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(int64, *model.ListOptions) error); ok {
|
||||
r1 = rf(_a0, _a1)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// OrgSecretUpdate provides a mock function with given fields: _a0, _a1
|
||||
func (_m *Service) OrgSecretUpdate(_a0 int64, _a1 *model.Secret) error {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for OrgSecretUpdate")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(int64, *model.Secret) error); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// SecretCreate provides a mock function with given fields: _a0, _a1
|
||||
func (_m *Service) SecretCreate(_a0 *model.Repo, _a1 *model.Secret) error {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for SecretCreate")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(*model.Repo, *model.Secret) error); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// SecretDelete provides a mock function with given fields: _a0, _a1
|
||||
func (_m *Service) SecretDelete(_a0 *model.Repo, _a1 string) error {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for SecretDelete")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(*model.Repo, string) error); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// SecretFind provides a mock function with given fields: _a0, _a1
|
||||
func (_m *Service) SecretFind(_a0 *model.Repo, _a1 string) (*model.Secret, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for SecretFind")
|
||||
}
|
||||
|
||||
var r0 *model.Secret
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(*model.Repo, string) (*model.Secret, error)); ok {
|
||||
return rf(_a0, _a1)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(*model.Repo, string) *model.Secret); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*model.Secret)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(*model.Repo, string) error); ok {
|
||||
r1 = rf(_a0, _a1)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// SecretList provides a mock function with given fields: _a0, _a1
|
||||
func (_m *Service) SecretList(_a0 *model.Repo, _a1 *model.ListOptions) ([]*model.Secret, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for SecretList")
|
||||
}
|
||||
|
||||
var r0 []*model.Secret
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(*model.Repo, *model.ListOptions) ([]*model.Secret, error)); ok {
|
||||
return rf(_a0, _a1)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(*model.Repo, *model.ListOptions) []*model.Secret); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*model.Secret)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(*model.Repo, *model.ListOptions) error); ok {
|
||||
r1 = rf(_a0, _a1)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// SecretListPipeline provides a mock function with given fields: _a0, _a1
|
||||
func (_m *Service) SecretListPipeline(_a0 *model.Repo, _a1 *model.Pipeline) ([]*model.Secret, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for SecretListPipeline")
|
||||
}
|
||||
|
||||
var r0 []*model.Secret
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(*model.Repo, *model.Pipeline) ([]*model.Secret, error)); ok {
|
||||
return rf(_a0, _a1)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(*model.Repo, *model.Pipeline) []*model.Secret); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*model.Secret)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(*model.Repo, *model.Pipeline) error); ok {
|
||||
r1 = rf(_a0, _a1)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// SecretUpdate provides a mock function with given fields: _a0, _a1
|
||||
func (_m *Service) SecretUpdate(_a0 *model.Repo, _a1 *model.Secret) error {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for SecretUpdate")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(*model.Repo, *model.Secret) error); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// NewService creates a new instance of Service. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
// The first argument is typically a *testing.T value.
|
||||
func NewService(t interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}) *Service {
|
||||
mock := &Service{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
|
@ -16,6 +16,8 @@ package secret
|
|||
|
||||
import "go.woodpecker-ci.org/woodpecker/v2/server/model"
|
||||
|
||||
//go:generate mockery --name Service --output mocks --case underscore
|
||||
|
||||
// Service defines a service for managing secrets.
|
||||
type Service interface {
|
||||
SecretListPipeline(*model.Repo, *model.Pipeline) ([]*model.Secret, error)
|
||||
|
|
|
@ -30,7 +30,7 @@ func (s storage) GetUserRemoteID(remoteID model.ForgeRemoteID, login string) (*m
|
|||
user := new(model.User)
|
||||
err := wrapGet(sess.Where("forge_remote_id = ?", remoteID).Get(user))
|
||||
if err != nil {
|
||||
user, err = s.getUserLogin(sess, login)
|
||||
return s.getUserLogin(sess, login)
|
||||
}
|
||||
return user, err
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"cancel": "Cancel",
|
||||
"login_with": "Login with {forge}",
|
||||
"login": "Login",
|
||||
"welcome": "Welcome to Woodpecker",
|
||||
"repos": "Repos",
|
||||
|
|
|
@ -7,11 +7,11 @@ export default () =>
|
|||
|
||||
user: useConfig().user,
|
||||
|
||||
authenticate(url?: string) {
|
||||
authenticate(url?: string, forgeId?: number) {
|
||||
if (url !== undefined) {
|
||||
const config = useUserConfig();
|
||||
config.setUserConfig('redirectUrl', url);
|
||||
}
|
||||
window.location.href = `${useConfig().rootPath}/authorize`;
|
||||
window.location.href = `${useConfig().rootPath}/authorize?forge_id=${forgeId}`;
|
||||
},
|
||||
}) as const;
|
||||
|
|
|
@ -21,7 +21,16 @@
|
|||
</div>
|
||||
<div class="flex justify-center items-center flex-col md:w-2/5 min-h-48 gap-4 text-center">
|
||||
<h1 class="text-xl text-wp-text-100">{{ $t('welcome') }}</h1>
|
||||
<Button @click="doLogin">{{ $t('login') }}</Button>
|
||||
<div class="flex flex-col gap-2">
|
||||
<Button
|
||||
v-for="forge in forges"
|
||||
:key="forge.id"
|
||||
:start-icon="forge.type === 'addon' ? 'repo' : forge.type"
|
||||
@click="doLogin(forge.id)"
|
||||
>
|
||||
{{ $t('login_with', { forge: getHostFromUrl(forge) }) }}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
@ -35,16 +44,30 @@ import { useRoute, useRouter } from 'vue-router';
|
|||
import WoodpeckerLogo from '~/assets/logo.svg?component';
|
||||
import Button from '~/components/atomic/Button.vue';
|
||||
import Error from '~/components/atomic/Error.vue';
|
||||
import useApiClient from '~/compositions/useApiClient';
|
||||
import useAuthentication from '~/compositions/useAuthentication';
|
||||
import type { Forge } from '~/lib/api/types';
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const authentication = useAuthentication();
|
||||
const i18n = useI18n();
|
||||
const apiClient = useApiClient();
|
||||
|
||||
function doLogin() {
|
||||
const forges = ref<Forge[]>([]);
|
||||
|
||||
function getHostFromUrl(forge: Forge) {
|
||||
if (!forge.url) {
|
||||
return forge.type.charAt(0).toUpperCase() + forge.type.slice(1);
|
||||
}
|
||||
|
||||
const url = new URL(forge.url);
|
||||
return url.hostname;
|
||||
}
|
||||
|
||||
function doLogin(forgeId?: number) {
|
||||
const url = typeof route.query.url === 'string' ? route.query.url : '';
|
||||
authentication.authenticate(url);
|
||||
authentication.authenticate(url, forgeId);
|
||||
}
|
||||
|
||||
const authErrorMessages = {
|
||||
|
@ -65,6 +88,8 @@ onMounted(async () => {
|
|||
return;
|
||||
}
|
||||
|
||||
forges.value = (await apiClient.getForges()) ?? [];
|
||||
|
||||
if (route.query.error) {
|
||||
const error = route.query.error as keyof typeof authErrorMessages;
|
||||
errorMessage.value = authErrorMessages[error] ?? error;
|
||||
|
|
Loading…
Reference in a new issue