mirror of https://github.com/agola-io/agola
Compare commits
6 Commits
60cbfc9808
...
9804b5b34e
Author | SHA1 | Date |
---|---|---|
Alessandro Pinna | 9804b5b34e | |
Simone Gotti | e697e9163e | |
Simone Gotti | 86579b03cf | |
alessandro.pinna | 3cc0b10097 | |
alessandro.pinna | 6c9bac15ad | |
alessandro.pinna | b78c9fbb1b |
|
@ -115,7 +115,7 @@ local task_build_push_images(name, target, push) =
|
|||
|||,
|
||||
},
|
||||
]) + [
|
||||
{ type: 'run', command: '/kaniko/executor --context=dir:///kaniko/agola --build-arg AGOLAWEB_IMAGE=sorintlab/agola-web:v0.9.0 --target %s %s' % [target, options] },
|
||||
{ type: 'run', command: '/kaniko/executor --context=dir:///kaniko/agola --build-arg AGOLAWEB_IMAGE=sorintlab/agola-web:v0.10.0 --target %s %s' % [target, options] },
|
||||
],
|
||||
depends: ['checkout code and save to workspace', 'integration tests', 'test docker driver'],
|
||||
};
|
||||
|
|
25
CHANGELOG.md
25
CHANGELOG.md
|
@ -1,5 +1,30 @@
|
|||
## Changelog
|
||||
|
||||
### v0.10.0
|
||||
|
||||
- gateway: unify/improve handling of authenticated user (@sgotti) [#525](https://github.com/agola-io/agola/pull/525)
|
||||
- gateway: move remaining get of current user from api to action (@sgotti) [#524](https://github.com/agola-io/agola/pull/524)
|
||||
- gateway: fix commit status and run webhook deliveries api (@alessandro-sorint) [#521](https://github.com/agola-io/agola/pull/521)
|
||||
- tests: fix wrong ProjectCommitStatusRedelivery test (@alessandro-sorint) [#522](https://github.com/agola-io/agola/pull/522)
|
||||
- cmd/export: close file descriptor (@testwill) [#516](https://github.com/agola-io/agola/pull/516)
|
||||
- objectstorage: multiple updates and changes (@sgotti) [#519](https://github.com/agola-io/agola/pull/519)
|
||||
- runservice: fix objectsCleaner lock key usage (@sgotti) [#520](https://github.com/agola-io/agola/pull/520)
|
||||
- util: use generic Ptr function (@sgotti) [#518](https://github.com/agola-io/agola/pull/518)
|
||||
- *: update dependencies (@sgotti) [#517](https://github.com/agola-io/agola/pull/517)
|
||||
- api: add some missing http content types headers. (@sgotti) [#514](https://github.com/agola-io/agola/pull/514)
|
||||
- config: add docker registries auth nil check (@alessandro-sorint) [#513](https://github.com/agola-io/agola/pull/513)
|
||||
- configstore: move logic from db to action handler (@sgotti) [#511](https://github.com/agola-io/agola/pull/511)
|
||||
- *: update dependencies (@sgotti) [#512](https://github.com/agola-io/agola/pull/512)
|
||||
- *: add detailed errors to api responses (@sgotti) [#507](https://github.com/agola-io/agola/pull/507)
|
||||
- *: use do method in http handlers (@sgotti) [#508](https://github.com/agola-io/agola/pull/508)
|
||||
- gateway: add action.APIErrorFromRemoteError (@sgotti) [#506](https://github.com/agola-io/agola/pull/506)
|
||||
- errors: split wrapped error from APIError message (@sgotti) [#505](https://github.com/agola-io/agola/pull/505)
|
||||
- configstore: move last bits of logic from api to action (@sgotti) [#504](https://github.com/agola-io/agola/pull/504)
|
||||
- configstore: fix wrong error handling (@sgotti) [#503](https://github.com/agola-io/agola/pull/503)
|
||||
- validation: add min/max length check to name validation (@sgotti) [#499](https://github.com/agola-io/agola/pull/499)
|
||||
- *: update to go 1.22 (@sgotti) [#498](https://github.com/agola-io/agola/pull/498)
|
||||
- sqlg updates (@sgotti) [#495](https://github.com/agola-io/agola/pull/495)
|
||||
|
||||
### v0.9.0
|
||||
|
||||
- agolademo: use docker compose (@sgotti) [#494](https://github.com/agola-io/agola/pull/494)
|
||||
|
|
|
@ -385,6 +385,10 @@ func (h *ActionHandler) DeleteProject(ctx context.Context, projectRef string) er
|
|||
return util.NewAPIError(util.ErrNotExist, util.WithAPIErrorMsg("project %q doesn't exist", projectRef), serrors.ProjectDoesNotExist())
|
||||
}
|
||||
|
||||
if err := h.d.DeleteUserProjectFavoritesByProjectID(tx, project.ID); err != nil {
|
||||
return util.NewAPIError(util.KindFromRemoteError(err), err)
|
||||
}
|
||||
|
||||
// TODO(sgotti) implement childs garbage collection
|
||||
if err := h.d.DeleteProject(tx, project.ID); err != nil {
|
||||
return errors.WithStack(err)
|
||||
|
|
|
@ -289,6 +289,10 @@ func (h *ActionHandler) DeleteUser(ctx context.Context, userRef string) error {
|
|||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
if err := h.d.DeleteUserProjectFavoritesByUserID(tx, user.ID); err != nil {
|
||||
return util.NewAPIError(util.KindFromRemoteError(err), err)
|
||||
}
|
||||
|
||||
if err := h.d.DeleteUser(tx, user.ID); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
package action
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/sorintlab/errors"
|
||||
|
||||
"agola.io/agola/internal/sqlg/sql"
|
||||
"agola.io/agola/internal/util"
|
||||
"agola.io/agola/services/configstore/types"
|
||||
)
|
||||
|
||||
type CreateUserProjectFavoriteRequest struct {
|
||||
UserRef string
|
||||
ProjectRef string
|
||||
}
|
||||
|
||||
func (h *ActionHandler) CreateUserProjectFavorite(ctx context.Context, req *CreateUserProjectFavoriteRequest) (*types.UserProjectFavorite, error) {
|
||||
var userProjectFavorite *types.UserProjectFavorite
|
||||
err := h.d.Do(ctx, func(tx *sql.Tx) error {
|
||||
var err error
|
||||
user, err := h.d.GetUser(tx, req.UserRef)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
if user == nil {
|
||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user with ref %q doesn't exist", req.UserRef))
|
||||
}
|
||||
|
||||
project, err := h.d.GetProject(tx, req.ProjectRef)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
if project == nil {
|
||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project with ref %q doesn't exist", req.ProjectRef))
|
||||
}
|
||||
|
||||
// check duplicate user project favorite
|
||||
userProjectFavorite, err = h.d.GetUserProjectFavorite(tx, user.ID, project.ID)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
if userProjectFavorite != nil {
|
||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user project favorite with user ref %q, project ref %q already exists", req.UserRef, req.ProjectRef))
|
||||
}
|
||||
|
||||
userProjectFavorite = types.NewUserProjectFavorite(tx)
|
||||
userProjectFavorite.UserID = user.ID
|
||||
userProjectFavorite.ProjectID = project.ID
|
||||
|
||||
if err := h.d.InsertUserProjectFavorite(tx, userProjectFavorite); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
return userProjectFavorite, errors.WithStack(err)
|
||||
}
|
||||
|
||||
func (h *ActionHandler) DeleteUserProjectFavorite(ctx context.Context, userRef, projectRef string) error {
|
||||
err := h.d.Do(ctx, func(tx *sql.Tx) error {
|
||||
user, err := h.d.GetUser(tx, userRef)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
if user == nil {
|
||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user with ref %q doesn't exist", userRef))
|
||||
}
|
||||
|
||||
project, err := h.d.GetProject(tx, projectRef)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
if project == nil {
|
||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project with ref %q doesn't exist", projectRef))
|
||||
}
|
||||
|
||||
// check project favorite existance
|
||||
userProjectFavorite, err := h.d.GetUserProjectFavorite(tx, user.ID, project.ID)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
if userProjectFavorite == nil {
|
||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user project favorite for user %q, project %q doesn't exist", userRef, projectRef))
|
||||
}
|
||||
|
||||
if err := h.d.DeleteUserProjectFavorite(tx, userProjectFavorite.ID); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
type GetUserProjectFavoritesRequest struct {
|
||||
UserRef string
|
||||
|
||||
StartUserProjectFavoriteID string
|
||||
|
||||
Limit int
|
||||
SortDirection types.SortDirection
|
||||
}
|
||||
|
||||
type GetUserProjectFavoritesResponse struct {
|
||||
UserProjectFavorites []*types.UserProjectFavorite
|
||||
|
||||
HasMore bool
|
||||
}
|
||||
|
||||
func (h *ActionHandler) GetUserProjectFavorites(ctx context.Context, req *GetUserProjectFavoritesRequest) (*GetUserProjectFavoritesResponse, error) {
|
||||
limit := req.Limit
|
||||
if limit > 0 {
|
||||
limit += 1
|
||||
}
|
||||
if req.SortDirection == "" {
|
||||
req.SortDirection = types.SortDirectionAsc
|
||||
}
|
||||
|
||||
var userProjectFavorites []*types.UserProjectFavorite
|
||||
err := h.d.Do(ctx, func(tx *sql.Tx) error {
|
||||
user, err := h.d.GetUser(tx, req.UserRef)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
if user == nil {
|
||||
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user with ref %q doesn't exist", req.UserRef))
|
||||
}
|
||||
|
||||
userProjectFavorites, err = h.d.GetUserProjectFavoritesByUserID(tx, user.ID, req.StartUserProjectFavoriteID, limit, req.SortDirection)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
var hasMore bool
|
||||
if req.Limit > 0 {
|
||||
hasMore = len(userProjectFavorites) > req.Limit
|
||||
if hasMore {
|
||||
userProjectFavorites = userProjectFavorites[0:req.Limit]
|
||||
}
|
||||
}
|
||||
|
||||
return &GetUserProjectFavoritesResponse{
|
||||
UserProjectFavorites: userProjectFavorites,
|
||||
HasMore: hasMore,
|
||||
}, nil
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
// Copyright 2024 Sorint.lab
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/sorintlab/errors"
|
||||
|
||||
"agola.io/agola/internal/services/configstore/action"
|
||||
"agola.io/agola/internal/util"
|
||||
"agola.io/agola/services/configstore/types"
|
||||
)
|
||||
|
||||
type CreateUserProjectFavoriteHandler struct {
|
||||
log zerolog.Logger
|
||||
ah *action.ActionHandler
|
||||
}
|
||||
|
||||
func NewCreateUserProjectFavoriteHandler(log zerolog.Logger, ah *action.ActionHandler) *CreateUserProjectFavoriteHandler {
|
||||
return &CreateUserProjectFavoriteHandler{log: log, ah: ah}
|
||||
}
|
||||
|
||||
func (h *CreateUserProjectFavoriteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
vars := mux.Vars(r)
|
||||
|
||||
userRef, err := url.PathUnescape(vars["userref"])
|
||||
if err != nil {
|
||||
util.HTTPError(w, util.NewAPIError(util.ErrBadRequest, err))
|
||||
return
|
||||
}
|
||||
|
||||
projectRef, err := url.PathUnescape(vars["projectref"])
|
||||
if err != nil {
|
||||
util.HTTPError(w, util.NewAPIError(util.ErrBadRequest, err))
|
||||
return
|
||||
}
|
||||
|
||||
areq := &action.CreateUserProjectFavoriteRequest{
|
||||
UserRef: userRef,
|
||||
ProjectRef: projectRef,
|
||||
}
|
||||
|
||||
userProjectFavorite, err := h.ah.CreateUserProjectFavorite(ctx, areq)
|
||||
if util.HTTPError(w, err) {
|
||||
h.log.Err(err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
if err := util.HTTPResponse(w, http.StatusCreated, userProjectFavorite); err != nil {
|
||||
h.log.Err(err).Send()
|
||||
}
|
||||
}
|
||||
|
||||
type DeleteUserProjectFavoriteHandler struct {
|
||||
log zerolog.Logger
|
||||
ah *action.ActionHandler
|
||||
}
|
||||
|
||||
func NewDeleteUserProjectFavoriteHandler(log zerolog.Logger, ah *action.ActionHandler) *DeleteUserProjectFavoriteHandler {
|
||||
return &DeleteUserProjectFavoriteHandler{log: log, ah: ah}
|
||||
}
|
||||
|
||||
func (h *DeleteUserProjectFavoriteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
vars := mux.Vars(r)
|
||||
|
||||
userRef, err := url.PathUnescape(vars["userref"])
|
||||
if err != nil {
|
||||
util.HTTPError(w, util.NewAPIError(util.ErrBadRequest, err))
|
||||
return
|
||||
}
|
||||
|
||||
projectRef, err := url.PathUnescape(vars["projectref"])
|
||||
if err != nil {
|
||||
util.HTTPError(w, util.NewAPIError(util.ErrBadRequest, err))
|
||||
return
|
||||
}
|
||||
|
||||
err = h.ah.DeleteUserProjectFavorite(ctx, userRef, projectRef)
|
||||
if util.HTTPError(w, err) {
|
||||
h.log.Err(err).Send()
|
||||
}
|
||||
if err := util.HTTPResponse(w, http.StatusNoContent, nil); err != nil {
|
||||
h.log.Err(err).Send()
|
||||
}
|
||||
}
|
||||
|
||||
type UserProjectFavoritesHandler struct {
|
||||
log zerolog.Logger
|
||||
ah *action.ActionHandler
|
||||
}
|
||||
|
||||
func NewUserProjectFavoritesHandler(log zerolog.Logger, ah *action.ActionHandler) *UserProjectFavoritesHandler {
|
||||
return &UserProjectFavoritesHandler{log: log, ah: ah}
|
||||
}
|
||||
|
||||
func (h *UserProjectFavoritesHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
res, err := h.do(w, r)
|
||||
if util.HTTPError(w, err) {
|
||||
h.log.Err(err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
if err := util.HTTPResponse(w, http.StatusOK, res); err != nil {
|
||||
h.log.Err(err).Send()
|
||||
}
|
||||
}
|
||||
|
||||
func (h *UserProjectFavoritesHandler) do(w http.ResponseWriter, r *http.Request) ([]*types.UserProjectFavorite, error) {
|
||||
ctx := r.Context()
|
||||
vars := mux.Vars(r)
|
||||
query := r.URL.Query()
|
||||
|
||||
ropts, err := parseRequestOptions(r)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
userRef, err := url.PathUnescape(vars["userref"])
|
||||
if err != nil {
|
||||
return nil, util.NewAPIError(util.ErrBadRequest, err)
|
||||
}
|
||||
|
||||
startUserProjectFavoriteID := query.Get("startuserprojectfavoriteid")
|
||||
|
||||
ares, err := h.ah.GetUserProjectFavorites(ctx, &action.GetUserProjectFavoritesRequest{UserRef: userRef, StartUserProjectFavoriteID: startUserProjectFavoriteID, Limit: ropts.Limit, SortDirection: ropts.SortDirection})
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
addHasMoreHeader(w, ares.HasMore)
|
||||
|
||||
return ares.UserProjectFavorites, nil
|
||||
}
|
|
@ -206,6 +206,10 @@ func (s *Configstore) setupDefaultRouter() http.Handler {
|
|||
deleteOrgInvitationHandler := api.NewDeleteOrgInvitationHandler(s.log, s.ah)
|
||||
orgInvitationHandler := api.NewOrgInvitationHandler(s.log, s.ah)
|
||||
|
||||
userProjectFavorites := api.NewUserProjectFavoritesHandler(s.log, s.ah)
|
||||
createUserProjectFavoriteHandler := api.NewCreateUserProjectFavoriteHandler(s.log, s.ah)
|
||||
deleteUserProjectFavoriteHandler := api.NewDeleteUserProjectFavoriteHandler(s.log, s.ah)
|
||||
|
||||
authHandler := handlers.NewInternalAuthChecker(s.log, s.c.APIToken)
|
||||
|
||||
router := mux.NewRouter()
|
||||
|
@ -283,6 +287,10 @@ func (s *Configstore) setupDefaultRouter() http.Handler {
|
|||
|
||||
apirouter.Handle("/linkedaccounts", linkedAccountsHandler).Methods("GET")
|
||||
|
||||
apirouter.Handle("/users/{userref}/projectfavorites", userProjectFavorites).Methods("GET")
|
||||
apirouter.Handle("/users/{userref}/projects/{projectref}/projectfavorites", createUserProjectFavoriteHandler).Methods("POST")
|
||||
apirouter.Handle("/users/{userref}/projects/{projectref}/projectfavorites", deleteUserProjectFavoriteHandler).Methods("DELETE")
|
||||
|
||||
apirouter.Handle("/maintenance", maintenanceStatusHandler).Methods("GET")
|
||||
apirouter.Handle("/maintenance", maintenanceModeHandler).Methods("PUT", "DELETE")
|
||||
|
||||
|
|
|
@ -152,6 +152,21 @@ func getVariables(ctx context.Context, cs *Configstore) ([]*types.Variable, erro
|
|||
return variables, errors.WithStack(err)
|
||||
}
|
||||
|
||||
func getUserProjectFavorites(ctx context.Context, cs *Configstore) ([]*types.UserProjectFavorite, error) {
|
||||
var userProjectFavorites []*types.UserProjectFavorite
|
||||
err := cs.d.Do(ctx, func(tx *sql.Tx) error {
|
||||
var err error
|
||||
userProjectFavorites, err = cs.d.GetUserProjectFavorites(tx)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return userProjectFavorites, errors.WithStack(err)
|
||||
}
|
||||
|
||||
func cmpDiffObject(x, y interface{}) cmp.Comparison {
|
||||
// Since postgres has microsecond time precision while go has nanosecond time precision we should check times with a microsecond margin
|
||||
return cmp.DeepEqual(x, y, cmpopts.IgnoreFields(sqlg.ObjectMeta{}, "TxID"), cmpopts.EquateApproxTime(1*time.Microsecond))
|
||||
|
@ -1955,3 +1970,241 @@ func TestOrgInvitation(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserProjectFavorite(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
log := testutil.NewLogger(t)
|
||||
|
||||
setupUsers := func(t *testing.T, ctx context.Context, cs *Configstore, limit int) {
|
||||
for i := 1; i <= limit; i++ {
|
||||
_, err := cs.ah.CreateUser(ctx, &action.CreateUserRequest{UserName: fmt.Sprintf("user%d", i)})
|
||||
testutil.NilError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
setupOrg := func(t *testing.T, ctx context.Context, cs *Configstore, creatorUserID string) {
|
||||
_, err := cs.ah.CreateOrg(ctx, &action.CreateOrgRequest{Name: "org01", Visibility: types.VisibilityPublic, CreatorUserID: creatorUserID})
|
||||
testutil.NilError(t, err)
|
||||
}
|
||||
|
||||
setupProjects := func(t *testing.T, ctx context.Context, cs *Configstore, limit int) {
|
||||
for i := 1; i <= limit; i++ {
|
||||
_, err := cs.ah.CreateProject(ctx, &action.CreateUpdateProjectRequest{Name: fmt.Sprintf("project%d", i), Parent: types.Parent{Kind: types.ObjectKindProjectGroup, ID: path.Join("org", "org01")}, Visibility: types.VisibilityPublic, RemoteRepositoryConfigType: types.RemoteRepositoryConfigTypeManual})
|
||||
testutil.NilError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
f func(ctx context.Context, t *testing.T, cs *Configstore)
|
||||
}{
|
||||
{
|
||||
name: "test create user project favorites",
|
||||
f: func(ctx context.Context, t *testing.T, cs *Configstore) {
|
||||
setupUsers(t, ctx, cs, 4)
|
||||
users, err := getUsers(ctx, cs)
|
||||
testutil.NilError(t, err)
|
||||
|
||||
userOwner := users[0]
|
||||
|
||||
setupOrg(t, ctx, cs, userOwner.ID)
|
||||
|
||||
setupProjects(t, ctx, cs, 4)
|
||||
projects, err := getProjects(ctx, cs)
|
||||
testutil.NilError(t, err)
|
||||
|
||||
var expectedUserProjectFavorites []*types.UserProjectFavorite
|
||||
|
||||
for i := 0; i < len(users); i++ {
|
||||
userProjectFavorite, err := cs.ah.CreateUserProjectFavorite(ctx, &action.CreateUserProjectFavoriteRequest{UserRef: fmt.Sprintf("user%d", i+1), ProjectRef: projects[i].ID})
|
||||
testutil.NilError(t, err)
|
||||
|
||||
expectedUserProjectFavorites = append(expectedUserProjectFavorites, userProjectFavorite)
|
||||
}
|
||||
|
||||
userProjectFavorites, err := getUserProjectFavorites(ctx, cs)
|
||||
testutil.NilError(t, err)
|
||||
|
||||
assert.Assert(t, cmpDiffObject(expectedUserProjectFavorites, userProjectFavorites))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "test user project favorite creation with already existing user project favorite",
|
||||
f: func(ctx context.Context, t *testing.T, cs *Configstore) {
|
||||
setupUsers(t, ctx, cs, 1)
|
||||
users, err := getUsers(ctx, cs)
|
||||
testutil.NilError(t, err)
|
||||
|
||||
user := users[0]
|
||||
|
||||
setupOrg(t, ctx, cs, user.ID)
|
||||
|
||||
setupProjects(t, ctx, cs, 1)
|
||||
projects, err := getProjects(ctx, cs)
|
||||
testutil.NilError(t, err)
|
||||
|
||||
_, err = cs.ah.CreateUserProjectFavorite(ctx, &action.CreateUserProjectFavoriteRequest{UserRef: "user1", ProjectRef: projects[0].ID})
|
||||
testutil.NilError(t, err)
|
||||
|
||||
expectedErr := util.NewAPIError(util.ErrBadRequest, errors.Errorf("user project favorite with user ref %q, project ref %q already exists", "user1", projects[0].ID))
|
||||
_, err = cs.ah.CreateUserProjectFavorite(ctx, &action.CreateUserProjectFavoriteRequest{UserRef: "user1", ProjectRef: projects[0].ID})
|
||||
assert.Error(t, err, expectedErr.Error())
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "test user project favorite creation with not existing user",
|
||||
f: func(ctx context.Context, t *testing.T, cs *Configstore) {
|
||||
setupUsers(t, ctx, cs, 1)
|
||||
users, err := getUsers(ctx, cs)
|
||||
testutil.NilError(t, err)
|
||||
|
||||
userOwner := users[0]
|
||||
|
||||
setupOrg(t, ctx, cs, userOwner.ID)
|
||||
|
||||
setupProjects(t, ctx, cs, 1)
|
||||
projects, err := getProjects(ctx, cs)
|
||||
testutil.NilError(t, err)
|
||||
|
||||
expectedErr := util.NewAPIError(util.ErrBadRequest, errors.Errorf("user with ref %q doesn't exist", "usertest"))
|
||||
_, err = cs.ah.CreateUserProjectFavorite(ctx, &action.CreateUserProjectFavoriteRequest{UserRef: "usertest", ProjectRef: projects[0].ID})
|
||||
assert.Error(t, err, expectedErr.Error())
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "test user project favorite creation with not existing project",
|
||||
f: func(ctx context.Context, t *testing.T, cs *Configstore) {
|
||||
setupUsers(t, ctx, cs, 1)
|
||||
users, err := getUsers(ctx, cs)
|
||||
testutil.NilError(t, err)
|
||||
|
||||
userOwner := users[0]
|
||||
|
||||
setupOrg(t, ctx, cs, userOwner.ID)
|
||||
|
||||
setupProjects(t, ctx, cs, 1)
|
||||
|
||||
expectedErr := util.NewAPIError(util.ErrBadRequest, errors.Errorf("project with ref %q doesn't exist", "projecttest"))
|
||||
_, err = cs.ah.CreateUserProjectFavorite(ctx, &action.CreateUserProjectFavoriteRequest{UserRef: users[0].ID, ProjectRef: "projecttest"})
|
||||
assert.Error(t, err, expectedErr.Error())
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "test user project favorite deletion",
|
||||
f: func(ctx context.Context, t *testing.T, cs *Configstore) {
|
||||
setupUsers(t, ctx, cs, 1)
|
||||
users, err := getUsers(ctx, cs)
|
||||
testutil.NilError(t, err)
|
||||
|
||||
userOwner := users[0]
|
||||
|
||||
setupOrg(t, ctx, cs, userOwner.ID)
|
||||
|
||||
setupProjects(t, ctx, cs, 1)
|
||||
projects, err := getProjects(ctx, cs)
|
||||
testutil.NilError(t, err)
|
||||
|
||||
_, err = cs.ah.CreateUserProjectFavorite(ctx, &action.CreateUserProjectFavoriteRequest{UserRef: "user1", ProjectRef: projects[0].ID})
|
||||
testutil.NilError(t, err)
|
||||
|
||||
err = cs.ah.DeleteUserProjectFavorite(ctx, "user1", projects[0].ID)
|
||||
testutil.NilError(t, err)
|
||||
|
||||
aresp, err := cs.ah.GetUserProjectFavorites(ctx, &action.GetUserProjectFavoritesRequest{UserRef: "user1"})
|
||||
testutil.NilError(t, err)
|
||||
|
||||
assert.Assert(t, cmp.Len(aresp.UserProjectFavorites, 0))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "test user project favorite deletion with not existing user project favorite",
|
||||
f: func(ctx context.Context, t *testing.T, cs *Configstore) {
|
||||
setupUsers(t, ctx, cs, 1)
|
||||
users, err := getUsers(ctx, cs)
|
||||
testutil.NilError(t, err)
|
||||
|
||||
userOwner := users[0]
|
||||
|
||||
setupOrg(t, ctx, cs, userOwner.ID)
|
||||
|
||||
setupProjects(t, ctx, cs, 1)
|
||||
projects, err := getProjects(ctx, cs)
|
||||
testutil.NilError(t, err)
|
||||
|
||||
expectedErr := util.NewAPIError(util.ErrBadRequest, errors.Errorf("user project favorite for user %q, project %q doesn't exist", "user1", projects[0].ID))
|
||||
err = cs.ah.DeleteUserProjectFavorite(ctx, "user1", projects[0].ID)
|
||||
assert.Error(t, err, expectedErr.Error())
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "test user deletion with existing user project favorite",
|
||||
f: func(ctx context.Context, t *testing.T, cs *Configstore) {
|
||||
setupUsers(t, ctx, cs, 1)
|
||||
users, err := getUsers(ctx, cs)
|
||||
testutil.NilError(t, err)
|
||||
|
||||
userOwner := users[0]
|
||||
|
||||
setupOrg(t, ctx, cs, userOwner.ID)
|
||||
|
||||
setupProjects(t, ctx, cs, 1)
|
||||
projects, err := getProjects(ctx, cs)
|
||||
testutil.NilError(t, err)
|
||||
|
||||
_, err = cs.ah.CreateUserProjectFavorite(ctx, &action.CreateUserProjectFavoriteRequest{UserRef: "user1", ProjectRef: projects[0].ID})
|
||||
testutil.NilError(t, err)
|
||||
|
||||
err = cs.ah.DeleteUser(ctx, "user1")
|
||||
testutil.NilError(t, err)
|
||||
|
||||
userProjectFavorites, err := getUserProjectFavorites(ctx, cs)
|
||||
testutil.NilError(t, err)
|
||||
|
||||
assert.Assert(t, cmp.Len(userProjectFavorites, 0))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "test user project deletion with existing project favorite",
|
||||
f: func(ctx context.Context, t *testing.T, cs *Configstore) {
|
||||
setupUsers(t, ctx, cs, 1)
|
||||
users, err := getUsers(ctx, cs)
|
||||
testutil.NilError(t, err)
|
||||
|
||||
userOwner := users[0]
|
||||
|
||||
setupOrg(t, ctx, cs, userOwner.ID)
|
||||
|
||||
setupProjects(t, ctx, cs, 1)
|
||||
projects, err := getProjects(ctx, cs)
|
||||
testutil.NilError(t, err)
|
||||
|
||||
_, err = cs.ah.CreateUserProjectFavorite(ctx, &action.CreateUserProjectFavoriteRequest{UserRef: "user1", ProjectRef: projects[0].ID})
|
||||
testutil.NilError(t, err)
|
||||
|
||||
err = cs.ah.DeleteProject(ctx, projects[0].ID)
|
||||
testutil.NilError(t, err)
|
||||
|
||||
userProjectFavorites, err := getUserProjectFavorites(ctx, cs)
|
||||
testutil.NilError(t, err)
|
||||
|
||||
assert.Assert(t, cmp.Len(userProjectFavorites, 0))
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
cs := setupConfigstore(ctx, t, log, dir)
|
||||
|
||||
t.Logf("starting cs")
|
||||
go func() { _ = cs.Run(ctx) }()
|
||||
|
||||
tt.f(ctx, t, cs)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -849,3 +849,72 @@ func (d *DB) DeleteOrgInvitationsByUserID(tx *sql.Tx, userID string) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DB) GetUserProjectFavorites(tx *sql.Tx) ([]*types.UserProjectFavorite, error) {
|
||||
q := userProjectFavoriteSelect()
|
||||
userProjectFavorites, _, err := d.fetchUserProjectFavorites(tx, q)
|
||||
return userProjectFavorites, errors.WithStack(err)
|
||||
}
|
||||
|
||||
func (d *DB) GetUserProjectFavorite(tx *sql.Tx, userID string, projectID string) (*types.UserProjectFavorite, error) {
|
||||
q := userProjectFavoriteSelect()
|
||||
q.Where(q.E("user_id", userID))
|
||||
q.Where(q.E("project_id", projectID))
|
||||
|
||||
userProjectFavorites, _, err := d.fetchUserProjectFavorites(tx, q)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
out, err := mustSingleRow(userProjectFavorites)
|
||||
return out, errors.WithStack(err)
|
||||
}
|
||||
|
||||
func (d *DB) GetUserProjectFavoritesByUserID(tx *sql.Tx, userID string, startUserProjectFavoriteID string, limit int, sortDirection types.SortDirection) ([]*types.UserProjectFavorite, error) {
|
||||
q := userProjectFavoriteSelect()
|
||||
q.Where(q.E("user_id", userID))
|
||||
|
||||
q.OrderBy("id")
|
||||
switch sortDirection {
|
||||
case types.SortDirectionAsc:
|
||||
q = q.Asc()
|
||||
case types.SortDirectionDesc:
|
||||
q = q.Desc()
|
||||
}
|
||||
if startUserProjectFavoriteID != "" {
|
||||
switch sortDirection {
|
||||
case types.SortDirectionAsc:
|
||||
q = q.Where(q.G("id", startUserProjectFavoriteID))
|
||||
case types.SortDirectionDesc:
|
||||
q = q.Where(q.L("id", startUserProjectFavoriteID))
|
||||
}
|
||||
}
|
||||
|
||||
if limit > 0 {
|
||||
q = q.Limit(limit)
|
||||
}
|
||||
|
||||
userProjectFavorites, _, err := d.fetchUserProjectFavorites(tx, q)
|
||||
|
||||
return userProjectFavorites, errors.WithStack(err)
|
||||
}
|
||||
|
||||
func (d *DB) DeleteUserProjectFavoritesByProjectID(tx *sql.Tx, projectID string) error {
|
||||
q := sq.NewDeleteBuilder()
|
||||
q.DeleteFrom("userprojectfavorite").Where(q.E("project_id", projectID))
|
||||
if _, err := d.exec(tx, q); err != nil {
|
||||
return errors.Wrap(err, "failed to delete userprojectfavorite")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DB) DeleteUserProjectFavoritesByUserID(tx *sql.Tx, userID string) error {
|
||||
q := sq.NewDeleteBuilder()
|
||||
q.DeleteFrom("userprojectfavorite").Where(q.E("user_id", userID))
|
||||
if _, err := d.exec(tx, q); err != nil {
|
||||
return errors.Wrap(err, "failed to delete userprojectfavorite")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ var DDLPostgres = []string{
|
|||
"create table if not exists secret (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamptz NOT NULL, update_time timestamptz NOT NULL, name varchar NOT NULL, parent_kind varchar NOT NULL, parent_id varchar NOT NULL, type varchar NOT NULL, data jsonb NOT NULL, secret_provider_id varchar NOT NULL, path varchar NOT NULL, PRIMARY KEY (id))",
|
||||
"create table if not exists variable (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamptz NOT NULL, update_time timestamptz NOT NULL, name varchar NOT NULL, parent_kind varchar NOT NULL, parent_id varchar NOT NULL, variable_values jsonb NOT NULL, PRIMARY KEY (id))",
|
||||
"create table if not exists orginvitation (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamptz NOT NULL, update_time timestamptz NOT NULL, user_id varchar NOT NULL, organization_id varchar NOT NULL, role varchar NOT NULL, PRIMARY KEY (id), foreign key (user_id) references user_t(id), foreign key (organization_id) references organization(id))",
|
||||
"create table if not exists userprojectfavorite (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamptz NOT NULL, update_time timestamptz NOT NULL, user_id varchar NOT NULL, project_id varchar NOT NULL, PRIMARY KEY (id), foreign key (user_id) references user_t(id), foreign key (project_id) references project(id))",
|
||||
|
||||
// indexes
|
||||
}
|
||||
|
@ -31,6 +32,7 @@ var DDLSqlite3 = []string{
|
|||
"create table if not exists secret (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamp NOT NULL, update_time timestamp NOT NULL, name varchar NOT NULL, parent_kind varchar NOT NULL, parent_id varchar NOT NULL, type varchar NOT NULL, data text NOT NULL, secret_provider_id varchar NOT NULL, path varchar NOT NULL, PRIMARY KEY (id))",
|
||||
"create table if not exists variable (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamp NOT NULL, update_time timestamp NOT NULL, name varchar NOT NULL, parent_kind varchar NOT NULL, parent_id varchar NOT NULL, variable_values text NOT NULL, PRIMARY KEY (id))",
|
||||
"create table if not exists orginvitation (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamp NOT NULL, update_time timestamp NOT NULL, user_id varchar NOT NULL, organization_id varchar NOT NULL, role varchar NOT NULL, PRIMARY KEY (id), foreign key (user_id) references user_t(id), foreign key (organization_id) references organization(id))",
|
||||
"create table if not exists userprojectfavorite (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamp NOT NULL, update_time timestamp NOT NULL, user_id varchar NOT NULL, project_id varchar NOT NULL, PRIMARY KEY (id), foreign key (user_id) references user_t(id), foreign key (project_id) references project(id))",
|
||||
|
||||
// indexes
|
||||
}
|
||||
|
|
|
@ -1479,6 +1479,139 @@ func (d *DB) insertRawOrgInvitation(tx *sql.Tx, v *types.OrgInvitation) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
userProjectFavoriteSelectColumns = func(additionalCols ...string) []string {
|
||||
columns := []string{"userprojectfavorite.id", "userprojectfavorite.revision", "userprojectfavorite.creation_time", "userprojectfavorite.update_time", "userprojectfavorite.user_id", "userprojectfavorite.project_id"}
|
||||
columns = append(columns, additionalCols...)
|
||||
|
||||
return columns
|
||||
}
|
||||
|
||||
userProjectFavoriteSelect = func(additionalCols ...string) *sq.SelectBuilder {
|
||||
return sq.NewSelectBuilder().Select(userProjectFavoriteSelectColumns(additionalCols...)...).From("userprojectfavorite")
|
||||
}
|
||||
)
|
||||
|
||||
func (d *DB) InsertOrUpdateUserProjectFavorite(tx *sql.Tx, v *types.UserProjectFavorite) error {
|
||||
var err error
|
||||
if v.Revision == 0 {
|
||||
err = d.InsertUserProjectFavorite(tx, v)
|
||||
} else {
|
||||
err = d.UpdateUserProjectFavorite(tx, v)
|
||||
}
|
||||
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
func (d *DB) InsertUserProjectFavorite(tx *sql.Tx, v *types.UserProjectFavorite) error {
|
||||
if v.Revision != 0 {
|
||||
return errors.Errorf("expected revision 0 got %d", v.Revision)
|
||||
}
|
||||
|
||||
if v.TxID != tx.ID() {
|
||||
return errors.Errorf("object was not created by this transaction")
|
||||
}
|
||||
|
||||
v.Revision = 1
|
||||
|
||||
now := time.Now()
|
||||
v.CreationTime = now
|
||||
v.UpdateTime = now
|
||||
|
||||
var err error
|
||||
|
||||
switch d.DBType() {
|
||||
case sql.Postgres:
|
||||
err = d.insertRawUserProjectFavoritePostgres(tx, v);
|
||||
case sql.Sqlite3:
|
||||
err = d.insertUserProjectFavoriteSqlite3(tx, v);
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
v.Revision = 0
|
||||
return errors.Wrap(err, "failed to insert userprojectfavorite")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DB) UpdateUserProjectFavorite(tx *sql.Tx, v *types.UserProjectFavorite) error {
|
||||
if v.Revision < 1 {
|
||||
return errors.Errorf("expected revision > 0 got %d", v.Revision)
|
||||
}
|
||||
|
||||
if v.TxID != tx.ID() {
|
||||
return errors.Errorf("object was not fetched by this transaction")
|
||||
}
|
||||
|
||||
curRevision := v.Revision
|
||||
v.Revision++
|
||||
|
||||
v.UpdateTime = time.Now()
|
||||
|
||||
var res stdsql.Result
|
||||
var err error
|
||||
switch d.DBType() {
|
||||
case sql.Postgres:
|
||||
res, err = d.updateUserProjectFavoritePostgres(tx, curRevision, v);
|
||||
case sql.Sqlite3:
|
||||
res, err = d.updateUserProjectFavoriteSqlite3(tx, curRevision, v);
|
||||
}
|
||||
if err != nil {
|
||||
v.Revision = curRevision
|
||||
return errors.Wrap(err, "failed to update userprojectfavorite")
|
||||
}
|
||||
|
||||
rows, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
v.Revision = curRevision
|
||||
return errors.Wrap(err, "failed to update userprojectfavorite")
|
||||
}
|
||||
|
||||
if rows != 1 {
|
||||
v.Revision = curRevision
|
||||
return sqlg.ErrConcurrent
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DB) deleteUserProjectFavorite(tx *sql.Tx, userProjectFavoriteID string) error {
|
||||
q := sq.NewDeleteBuilder()
|
||||
q.DeleteFrom("userprojectfavorite").Where(q.E("id", userProjectFavoriteID))
|
||||
|
||||
if _, err := d.exec(tx, q); err != nil {
|
||||
return errors.Wrap(err, "failed to delete userProjectFavorite")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DB) DeleteUserProjectFavorite(tx *sql.Tx, id string) error {
|
||||
return d.deleteUserProjectFavorite(tx, id)
|
||||
}
|
||||
|
||||
// insertRawUserProjectFavorite should be used only for import.
|
||||
// * It won't update object times.
|
||||
// * It will insert values for sequences.
|
||||
func (d *DB) insertRawUserProjectFavorite(tx *sql.Tx, v *types.UserProjectFavorite) error {
|
||||
v.Revision = 1
|
||||
|
||||
var err error
|
||||
switch d.DBType() {
|
||||
case sql.Postgres:
|
||||
err = d.insertRawUserProjectFavoritePostgres(tx, v);
|
||||
case sql.Sqlite3:
|
||||
err = d.insertRawUserProjectFavoriteSqlite3(tx, v);
|
||||
}
|
||||
if err != nil {
|
||||
v.Revision = 0
|
||||
return errors.Wrap(err, "failed to insert userprojectfavorite")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DB) UnmarshalExportObject(data []byte) (sqlg.Object, error) {
|
||||
type exportObjectExportMeta struct {
|
||||
ExportMeta sqlg.ExportMeta `json:"exportMeta"`
|
||||
|
@ -1514,6 +1647,8 @@ func (d *DB) UnmarshalExportObject(data []byte) (sqlg.Object, error) {
|
|||
obj = &types.Variable{}
|
||||
case "OrgInvitation":
|
||||
obj = &types.OrgInvitation{}
|
||||
case "UserProjectFavorite":
|
||||
obj = &types.UserProjectFavorite{}
|
||||
|
||||
default:
|
||||
panic(errors.Errorf("unknown object kind %q, data: %s", om.ExportMeta.Kind, data))
|
||||
|
@ -1550,6 +1685,8 @@ func (d *DB) InsertRawObject(tx *sql.Tx, obj sqlg.Object) error {
|
|||
return d.insertRawVariable(tx, o)
|
||||
case *types.OrgInvitation:
|
||||
return d.insertRawOrgInvitation(tx, o)
|
||||
case *types.UserProjectFavorite:
|
||||
return d.insertRawUserProjectFavorite(tx, o)
|
||||
|
||||
default:
|
||||
panic(errors.Errorf("unknown object type %T", obj))
|
||||
|
@ -1580,6 +1717,8 @@ func (d *DB) SelectObject(kind string) *sq.SelectBuilder {
|
|||
return variableSelect()
|
||||
case "OrgInvitation":
|
||||
return orgInvitationSelect()
|
||||
case "UserProjectFavorite":
|
||||
return userProjectFavoriteSelect()
|
||||
|
||||
default:
|
||||
panic(errors.Errorf("unknown object kind %q", kind))
|
||||
|
@ -1719,6 +1858,18 @@ func (d *DB) FetchObjects(tx *sql.Tx, kind string, q sq.Builder) ([]sqlg.Object,
|
|||
objs[i] = fobj
|
||||
}
|
||||
|
||||
return objs, nil
|
||||
case "UserProjectFavorite":
|
||||
fobjs, _, err := d.fetchUserProjectFavorites(tx, q)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
objs := make([]sqlg.Object, len(fobjs))
|
||||
for i, fobj := range fobjs {
|
||||
objs[i] = fobj
|
||||
}
|
||||
|
||||
return objs, nil
|
||||
|
||||
default:
|
||||
|
@ -1859,6 +2010,18 @@ func (d *DB) ObjectToExportJSON(obj sqlg.Object, e *json.Encoder) error {
|
|||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
case *types.UserProjectFavorite:
|
||||
type exportObject struct {
|
||||
ExportMeta sqlg.ExportMeta `json:"exportMeta"`
|
||||
|
||||
*types.UserProjectFavorite
|
||||
}
|
||||
|
||||
if err := e.Encode(&exportObject{ExportMeta: sqlg.ExportMeta{ Kind: "UserProjectFavorite" }, UserProjectFavorite: o}); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
default:
|
||||
|
|
|
@ -543,3 +543,49 @@ func (d *DB) insertRawOrgInvitationPostgres(tx *sql.Tx, orginvitation *types.Org
|
|||
|
||||
return nil
|
||||
}
|
||||
var (
|
||||
userProjectFavoriteInsertPostgres = func(inID string, inRevision uint64, inCreationTime time.Time, inUpdateTime time.Time, inUserID string, inProjectID string) *sq.InsertBuilder {
|
||||
ib:= sq.NewInsertBuilder()
|
||||
return ib.InsertInto("userprojectfavorite").Cols("id", "revision", "creation_time", "update_time", "user_id", "project_id").Values(inID, inRevision, inCreationTime, inUpdateTime, inUserID, inProjectID)
|
||||
}
|
||||
userProjectFavoriteUpdatePostgres = func(curRevision uint64, inID string, inRevision uint64, inCreationTime time.Time, inUpdateTime time.Time, inUserID string, inProjectID string) *sq.UpdateBuilder {
|
||||
ub:= sq.NewUpdateBuilder()
|
||||
return ub.Update("userprojectfavorite").Set(ub.Assign("id", inID), ub.Assign("revision", inRevision), ub.Assign("creation_time", inCreationTime), ub.Assign("update_time", inUpdateTime), ub.Assign("user_id", inUserID), ub.Assign("project_id", inProjectID)).Where(ub.E("id", inID), ub.E("revision", curRevision))
|
||||
}
|
||||
|
||||
userProjectFavoriteInsertRawPostgres = func(inID string, inRevision uint64, inCreationTime time.Time, inUpdateTime time.Time, inUserID string, inProjectID string) *sq.InsertBuilder {
|
||||
ib:= sq.NewInsertBuilder()
|
||||
return ib.InsertInto("userprojectfavorite").Cols("id", "revision", "creation_time", "update_time", "user_id", "project_id").SQL("OVERRIDING SYSTEM VALUE").Values(inID, inRevision, inCreationTime, inUpdateTime, inUserID, inProjectID)
|
||||
}
|
||||
)
|
||||
|
||||
func (d *DB) insertUserProjectFavoritePostgres(tx *sql.Tx, userprojectfavorite *types.UserProjectFavorite) error {
|
||||
q := userProjectFavoriteInsertPostgres(userprojectfavorite.ID, userprojectfavorite.Revision, userprojectfavorite.CreationTime, userprojectfavorite.UpdateTime, userprojectfavorite.UserID, userprojectfavorite.ProjectID)
|
||||
|
||||
if _, err := d.exec(tx, q); err != nil {
|
||||
return errors.Wrap(err, "failed to insert userProjectFavorite")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DB) updateUserProjectFavoritePostgres(tx *sql.Tx, curRevision uint64, userprojectfavorite *types.UserProjectFavorite) (stdsql.Result, error) {
|
||||
q := userProjectFavoriteUpdatePostgres(curRevision, userprojectfavorite.ID, userprojectfavorite.Revision, userprojectfavorite.CreationTime, userprojectfavorite.UpdateTime, userprojectfavorite.UserID, userprojectfavorite.ProjectID)
|
||||
|
||||
res, err := d.exec(tx, q)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to update userProjectFavorite")
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (d *DB) insertRawUserProjectFavoritePostgres(tx *sql.Tx, userprojectfavorite *types.UserProjectFavorite) error {
|
||||
q := userProjectFavoriteInsertRawPostgres(userprojectfavorite.ID, userprojectfavorite.Revision, userprojectfavorite.CreationTime, userprojectfavorite.UpdateTime, userprojectfavorite.UserID, userprojectfavorite.ProjectID)
|
||||
|
||||
if _, err := d.exec(tx, q); err != nil {
|
||||
return errors.Wrap(err, "failed to insert userProjectFavorite")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -543,3 +543,49 @@ func (d *DB) insertRawOrgInvitationSqlite3(tx *sql.Tx, orginvitation *types.OrgI
|
|||
|
||||
return nil
|
||||
}
|
||||
var (
|
||||
userProjectFavoriteInsertSqlite3 = func(inID string, inRevision uint64, inCreationTime time.Time, inUpdateTime time.Time, inUserID string, inProjectID string) *sq.InsertBuilder {
|
||||
ib:= sq.NewInsertBuilder()
|
||||
return ib.InsertInto("userprojectfavorite").Cols("id", "revision", "creation_time", "update_time", "user_id", "project_id").Values(inID, inRevision, inCreationTime, inUpdateTime, inUserID, inProjectID)
|
||||
}
|
||||
userProjectFavoriteUpdateSqlite3 = func(curRevision uint64, inID string, inRevision uint64, inCreationTime time.Time, inUpdateTime time.Time, inUserID string, inProjectID string) *sq.UpdateBuilder {
|
||||
ub:= sq.NewUpdateBuilder()
|
||||
return ub.Update("userprojectfavorite").Set(ub.Assign("id", inID), ub.Assign("revision", inRevision), ub.Assign("creation_time", inCreationTime), ub.Assign("update_time", inUpdateTime), ub.Assign("user_id", inUserID), ub.Assign("project_id", inProjectID)).Where(ub.E("id", inID), ub.E("revision", curRevision))
|
||||
}
|
||||
|
||||
userProjectFavoriteInsertRawSqlite3 = func(inID string, inRevision uint64, inCreationTime time.Time, inUpdateTime time.Time, inUserID string, inProjectID string) *sq.InsertBuilder {
|
||||
ib:= sq.NewInsertBuilder()
|
||||
return ib.InsertInto("userprojectfavorite").Cols("id", "revision", "creation_time", "update_time", "user_id", "project_id").SQL("").Values(inID, inRevision, inCreationTime, inUpdateTime, inUserID, inProjectID)
|
||||
}
|
||||
)
|
||||
|
||||
func (d *DB) insertUserProjectFavoriteSqlite3(tx *sql.Tx, userprojectfavorite *types.UserProjectFavorite) error {
|
||||
q := userProjectFavoriteInsertSqlite3(userprojectfavorite.ID, userprojectfavorite.Revision, userprojectfavorite.CreationTime, userprojectfavorite.UpdateTime, userprojectfavorite.UserID, userprojectfavorite.ProjectID)
|
||||
|
||||
if _, err := d.exec(tx, q); err != nil {
|
||||
return errors.Wrap(err, "failed to insert userProjectFavorite")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DB) updateUserProjectFavoriteSqlite3(tx *sql.Tx, curRevision uint64, userprojectfavorite *types.UserProjectFavorite) (stdsql.Result, error) {
|
||||
q := userProjectFavoriteUpdateSqlite3(curRevision, userprojectfavorite.ID, userprojectfavorite.Revision, userprojectfavorite.CreationTime, userprojectfavorite.UpdateTime, userprojectfavorite.UserID, userprojectfavorite.ProjectID)
|
||||
|
||||
res, err := d.exec(tx, q)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to update userProjectFavorite")
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (d *DB) insertRawUserProjectFavoriteSqlite3(tx *sql.Tx, userprojectfavorite *types.UserProjectFavorite) error {
|
||||
q := userProjectFavoriteInsertRawSqlite3(userprojectfavorite.ID, userprojectfavorite.Revision, userprojectfavorite.CreationTime, userprojectfavorite.UpdateTime, userprojectfavorite.UserID, userprojectfavorite.ProjectID)
|
||||
|
||||
if _, err := d.exec(tx, q); err != nil {
|
||||
return errors.Wrap(err, "failed to insert userProjectFavorite")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1260,3 +1260,107 @@ func (d *DB) OrgInvitationFromArray(a []any, txID string) (*types.OrgInvitation,
|
|||
|
||||
return v, v.ID, nil
|
||||
}
|
||||
|
||||
func (d *DB) fetchUserProjectFavorites(tx *sql.Tx, q sq.Builder) ([]*types.UserProjectFavorite, []string, error) {
|
||||
rows, err := d.query(tx, q)
|
||||
if err != nil {
|
||||
return nil, nil, errors.WithStack(err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
return d.scanUserProjectFavorites(rows, tx.ID(), 0)
|
||||
}
|
||||
|
||||
func (d *DB) fetchUserProjectFavoritesSkipLastFields(tx *sql.Tx, q sq.Builder, skipFieldsCount uint) ([]*types.UserProjectFavorite, []string, error) {
|
||||
rows, err := d.query(tx, q)
|
||||
if err != nil {
|
||||
return nil, nil, errors.WithStack(err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
return d.scanUserProjectFavorites(rows, tx.ID(), skipFieldsCount)
|
||||
}
|
||||
|
||||
func (d *DB) scanUserProjectFavorite(rows *stdsql.Rows, skipFieldsCount uint) (*types.UserProjectFavorite, string, error) {
|
||||
|
||||
v := &types.UserProjectFavorite{}
|
||||
|
||||
var vi any = v
|
||||
if x, ok := vi.(sqlg.Initer); ok {
|
||||
x.Init()
|
||||
}
|
||||
|
||||
fields := []any{&v.ID, &v.Revision, &v.CreationTime, &v.UpdateTime, &v.UserID, &v.ProjectID}
|
||||
|
||||
for i := uint(0); i < skipFieldsCount; i++ {
|
||||
fields = append(fields, new(any))
|
||||
}
|
||||
|
||||
if err := rows.Scan(fields...); err != nil {
|
||||
return nil, "", errors.Wrap(err, "failed to scan row")
|
||||
}
|
||||
|
||||
if x, ok := vi.(sqlg.PreJSONSetupper); ok {
|
||||
if err := x.PreJSON(); err != nil {
|
||||
return nil, "", errors.Wrap(err, "prejson error")
|
||||
}
|
||||
}
|
||||
|
||||
return v, v.ID, nil
|
||||
}
|
||||
|
||||
func (d *DB) scanUserProjectFavorites(rows *stdsql.Rows, txID string, skipFieldsCount uint) ([]*types.UserProjectFavorite, []string, error) {
|
||||
vs := []*types.UserProjectFavorite{}
|
||||
ids := []string{}
|
||||
for rows.Next() {
|
||||
v, id, err := d.scanUserProjectFavorite(rows, skipFieldsCount)
|
||||
if err != nil {
|
||||
rows.Close()
|
||||
return nil, nil, errors.WithStack(err)
|
||||
}
|
||||
v.TxID = txID
|
||||
vs = append(vs, v)
|
||||
ids = append(ids, id)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, nil, errors.WithStack(err)
|
||||
}
|
||||
return vs, ids, nil
|
||||
}
|
||||
|
||||
func (d *DB) UserProjectFavoriteArray() []any {
|
||||
a := []any{}
|
||||
a = append(a, new(string))
|
||||
a = append(a, new(uint64))
|
||||
a = append(a, new(time.Time))
|
||||
a = append(a, new(time.Time))
|
||||
a = append(a, new(string))
|
||||
a = append(a, new(string))
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
func (d *DB) UserProjectFavoriteFromArray(a []any, txID string) (*types.UserProjectFavorite, string, error) {
|
||||
v := &types.UserProjectFavorite{}
|
||||
|
||||
var vi any = v
|
||||
if x, ok := vi.(sqlg.Initer); ok {
|
||||
x.Init()
|
||||
}
|
||||
v.ID = *a[0].(*string)
|
||||
v.Revision = *a[1].(*uint64)
|
||||
v.CreationTime = *a[2].(*time.Time)
|
||||
v.UpdateTime = *a[3].(*time.Time)
|
||||
v.UserID = *a[4].(*string)
|
||||
v.ProjectID = *a[5].(*string)
|
||||
|
||||
if x, ok := vi.(sqlg.PreJSONSetupper); ok {
|
||||
if err := x.PreJSON(); err != nil {
|
||||
return nil, "", errors.Wrap(err, "prejson error")
|
||||
}
|
||||
}
|
||||
|
||||
v.TxID = txID
|
||||
|
||||
return v, v.ID, nil
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
"github.com/sorintlab/errors"
|
||||
)
|
||||
|
||||
func (d *DB) Version() uint { return 3 }
|
||||
func (d *DB) Version() uint { return 4 }
|
||||
|
||||
func (d *DB) DDL() []string {
|
||||
switch d.DBType() {
|
||||
|
|
|
@ -14,6 +14,7 @@ func (d *DB) MigrateFuncs() map[uint]sqlg.MigrateFunc {
|
|||
return map[uint]sqlg.MigrateFunc{
|
||||
2: d.migrateV2,
|
||||
3: d.migrateV3,
|
||||
4: d.migrateV4,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,3 +144,29 @@ func (d *DB) migrateV3(tx *sql.Tx) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DB) migrateV4(tx *sql.Tx) error {
|
||||
var ddlPostgres = []string{
|
||||
"create table if not exists userprojectfavorite (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamptz NOT NULL, update_time timestamptz NOT NULL, user_id varchar NOT NULL, project_id varchar NOT NULL, PRIMARY KEY (id), foreign key (user_id) references user_t(id), foreign key (project_id) references project(id))",
|
||||
}
|
||||
|
||||
var ddlSqlite3 = []string{
|
||||
"create table if not exists userprojectfavorite (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamp NOT NULL, update_time timestamp NOT NULL, user_id varchar NOT NULL, project_id varchar NOT NULL, PRIMARY KEY (id), foreign key (user_id) references user_t(id), foreign key (project_id) references project(id))",
|
||||
}
|
||||
|
||||
var stmts []string
|
||||
switch d.sdb.Type() {
|
||||
case sql.Postgres:
|
||||
stmts = ddlPostgres
|
||||
case sql.Sqlite3:
|
||||
stmts = ddlSqlite3
|
||||
}
|
||||
|
||||
for _, stmt := range stmts {
|
||||
if _, err := tx.Exec(stmt); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
Version = uint(3)
|
||||
Version = uint(4)
|
||||
)
|
||||
|
||||
const TypesImport = "agola.io/agola/services/configstore/types"
|
||||
|
@ -138,4 +138,14 @@ var ObjectsInfo = []sqlg.ObjectInfo{
|
|||
"foreign key (organization_id) references organization(id)",
|
||||
},
|
||||
},
|
||||
{Name: "UserProjectFavorite", Table: "userprojectfavorite",
|
||||
Fields: []sqlg.ObjectField{
|
||||
{Name: "UserID", Type: "string"},
|
||||
{Name: "ProjectID", Type: "string"},
|
||||
},
|
||||
Constraints: []string{
|
||||
"foreign key (user_id) references user_t(id)",
|
||||
"foreign key (project_id) references project(id)",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -0,0 +1,675 @@
|
|||
{
|
||||
"ddl": {
|
||||
"postgres": [
|
||||
"create table if not exists remotesource (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamptz NOT NULL, update_time timestamptz NOT NULL, name varchar NOT NULL, apiurl varchar NOT NULL, skip_verify boolean NOT NULL, type varchar NOT NULL, auth_type varchar NOT NULL, oauth2_client_id varchar NOT NULL, oauth2_client_secret varchar NOT NULL, ssh_host_key varchar NOT NULL, skip_ssh_host_key_check boolean NOT NULL, registration_enabled boolean NOT NULL, login_enabled boolean NOT NULL, PRIMARY KEY (id))",
|
||||
"create table if not exists user_t (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamptz NOT NULL, update_time timestamptz NOT NULL, name varchar NOT NULL, secret varchar NOT NULL, admin boolean NOT NULL, PRIMARY KEY (id))",
|
||||
"create table if not exists usertoken (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamptz NOT NULL, update_time timestamptz NOT NULL, user_id varchar NOT NULL, name varchar NOT NULL, value varchar NOT NULL, PRIMARY KEY (id), foreign key (user_id) references user_t(id))",
|
||||
"create table if not exists linkedaccount (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamptz NOT NULL, update_time timestamptz NOT NULL, user_id varchar NOT NULL, remote_user_id varchar NOT NULL, remote_user_name varchar NOT NULL, remote_user_avatar_url varchar NOT NULL, remote_source_id varchar NOT NULL, user_access_token varchar NOT NULL, oauth2_access_token varchar NOT NULL, oauth2_refresh_token varchar NOT NULL, oauth2_access_token_expires_at timestamptz NOT NULL, PRIMARY KEY (id), foreign key (user_id) references user_t(id), foreign key (remote_source_id) references remotesource(id))",
|
||||
"create table if not exists organization (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamptz NOT NULL, update_time timestamptz NOT NULL, name varchar NOT NULL, visibility varchar NOT NULL, creator_user_id varchar NOT NULL, PRIMARY KEY (id))",
|
||||
"create table if not exists orgmember (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamptz NOT NULL, update_time timestamptz NOT NULL, organization_id varchar NOT NULL, user_id varchar NOT NULL, member_role varchar NOT NULL, PRIMARY KEY (id), foreign key (organization_id) references organization(id), foreign key (user_id) references user_t(id))",
|
||||
"create table if not exists projectgroup (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamptz NOT NULL, update_time timestamptz NOT NULL, name varchar NOT NULL, parent_kind varchar NOT NULL, parent_id varchar NOT NULL, visibility varchar NOT NULL, PRIMARY KEY (id))",
|
||||
"create table if not exists project (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamptz NOT NULL, update_time timestamptz NOT NULL, name varchar NOT NULL, parent_kind varchar NOT NULL, parent_id varchar NOT NULL, secret varchar NOT NULL, visibility varchar NOT NULL, remote_repository_config_type varchar NOT NULL, remote_source_id varchar NOT NULL, linked_account_id varchar NOT NULL, repository_id varchar NOT NULL, repository_path varchar NOT NULL, ssh_private_key varchar NOT NULL, skip_ssh_host_key_check boolean NOT NULL, webhook_secret varchar NOT NULL, pass_vars_to_forked_pr boolean NOT NULL, default_branch varchar NOT NULL, members_can_perform_run_actions boolean NOT NULL, PRIMARY KEY (id))",
|
||||
"create table if not exists secret (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamptz NOT NULL, update_time timestamptz NOT NULL, name varchar NOT NULL, parent_kind varchar NOT NULL, parent_id varchar NOT NULL, type varchar NOT NULL, data jsonb NOT NULL, secret_provider_id varchar NOT NULL, path varchar NOT NULL, PRIMARY KEY (id))",
|
||||
"create table if not exists variable (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamptz NOT NULL, update_time timestamptz NOT NULL, name varchar NOT NULL, parent_kind varchar NOT NULL, parent_id varchar NOT NULL, variable_values jsonb NOT NULL, PRIMARY KEY (id))",
|
||||
"create table if not exists orginvitation (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamptz NOT NULL, update_time timestamptz NOT NULL, user_id varchar NOT NULL, organization_id varchar NOT NULL, role varchar NOT NULL, PRIMARY KEY (id), foreign key (user_id) references user_t(id), foreign key (organization_id) references organization(id))",
|
||||
"create table if not exists userprojectfavorite (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamptz NOT NULL, update_time timestamptz NOT NULL, user_id varchar NOT NULL, project_id varchar NOT NULL, PRIMARY KEY (id), foreign key (user_id) references user_t(id), foreign key (project_id) references project(id))"
|
||||
],
|
||||
"sqlite3": [
|
||||
"create table if not exists remotesource (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamp NOT NULL, update_time timestamp NOT NULL, name varchar NOT NULL, apiurl varchar NOT NULL, skip_verify integer NOT NULL, type varchar NOT NULL, auth_type varchar NOT NULL, oauth2_client_id varchar NOT NULL, oauth2_client_secret varchar NOT NULL, ssh_host_key varchar NOT NULL, skip_ssh_host_key_check integer NOT NULL, registration_enabled integer NOT NULL, login_enabled integer NOT NULL, PRIMARY KEY (id))",
|
||||
"create table if not exists user_t (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamp NOT NULL, update_time timestamp NOT NULL, name varchar NOT NULL, secret varchar NOT NULL, admin integer NOT NULL, PRIMARY KEY (id))",
|
||||
"create table if not exists usertoken (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamp NOT NULL, update_time timestamp NOT NULL, user_id varchar NOT NULL, name varchar NOT NULL, value varchar NOT NULL, PRIMARY KEY (id), foreign key (user_id) references user_t(id))",
|
||||
"create table if not exists linkedaccount (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamp NOT NULL, update_time timestamp NOT NULL, user_id varchar NOT NULL, remote_user_id varchar NOT NULL, remote_user_name varchar NOT NULL, remote_user_avatar_url varchar NOT NULL, remote_source_id varchar NOT NULL, user_access_token varchar NOT NULL, oauth2_access_token varchar NOT NULL, oauth2_refresh_token varchar NOT NULL, oauth2_access_token_expires_at timestamp NOT NULL, PRIMARY KEY (id), foreign key (user_id) references user_t(id), foreign key (remote_source_id) references remotesource(id))",
|
||||
"create table if not exists organization (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamp NOT NULL, update_time timestamp NOT NULL, name varchar NOT NULL, visibility varchar NOT NULL, creator_user_id varchar NOT NULL, PRIMARY KEY (id))",
|
||||
"create table if not exists orgmember (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamp NOT NULL, update_time timestamp NOT NULL, organization_id varchar NOT NULL, user_id varchar NOT NULL, member_role varchar NOT NULL, PRIMARY KEY (id), foreign key (organization_id) references organization(id), foreign key (user_id) references user_t(id))",
|
||||
"create table if not exists projectgroup (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamp NOT NULL, update_time timestamp NOT NULL, name varchar NOT NULL, parent_kind varchar NOT NULL, parent_id varchar NOT NULL, visibility varchar NOT NULL, PRIMARY KEY (id))",
|
||||
"create table if not exists project (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamp NOT NULL, update_time timestamp NOT NULL, name varchar NOT NULL, parent_kind varchar NOT NULL, parent_id varchar NOT NULL, secret varchar NOT NULL, visibility varchar NOT NULL, remote_repository_config_type varchar NOT NULL, remote_source_id varchar NOT NULL, linked_account_id varchar NOT NULL, repository_id varchar NOT NULL, repository_path varchar NOT NULL, ssh_private_key varchar NOT NULL, skip_ssh_host_key_check integer NOT NULL, webhook_secret varchar NOT NULL, pass_vars_to_forked_pr integer NOT NULL, default_branch varchar NOT NULL, members_can_perform_run_actions integer NOT NULL, PRIMARY KEY (id))",
|
||||
"create table if not exists secret (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamp NOT NULL, update_time timestamp NOT NULL, name varchar NOT NULL, parent_kind varchar NOT NULL, parent_id varchar NOT NULL, type varchar NOT NULL, data text NOT NULL, secret_provider_id varchar NOT NULL, path varchar NOT NULL, PRIMARY KEY (id))",
|
||||
"create table if not exists variable (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamp NOT NULL, update_time timestamp NOT NULL, name varchar NOT NULL, parent_kind varchar NOT NULL, parent_id varchar NOT NULL, variable_values text NOT NULL, PRIMARY KEY (id))",
|
||||
"create table if not exists orginvitation (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamp NOT NULL, update_time timestamp NOT NULL, user_id varchar NOT NULL, organization_id varchar NOT NULL, role varchar NOT NULL, PRIMARY KEY (id), foreign key (user_id) references user_t(id), foreign key (organization_id) references organization(id))",
|
||||
"create table if not exists userprojectfavorite (id varchar NOT NULL, revision bigint NOT NULL, creation_time timestamp NOT NULL, update_time timestamp NOT NULL, user_id varchar NOT NULL, project_id varchar NOT NULL, PRIMARY KEY (id), foreign key (user_id) references user_t(id), foreign key (project_id) references project(id))"
|
||||
]
|
||||
},
|
||||
"sequences": [],
|
||||
"tables": [
|
||||
{
|
||||
"name": "remotesource",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "revision",
|
||||
"type": "uint64",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "creation_time",
|
||||
"type": "time.Time",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "update_time",
|
||||
"type": "time.Time",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "apiurl",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "skip_verify",
|
||||
"type": "bool",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "type",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "auth_type",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "oauth2_client_id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "oauth2_client_secret",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "ssh_host_key",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "skip_ssh_host_key_check",
|
||||
"type": "bool",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "registration_enabled",
|
||||
"type": "bool",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "login_enabled",
|
||||
"type": "bool",
|
||||
"nullable": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "user_t",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "revision",
|
||||
"type": "uint64",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "creation_time",
|
||||
"type": "time.Time",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "update_time",
|
||||
"type": "time.Time",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "secret",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "admin",
|
||||
"type": "bool",
|
||||
"nullable": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "usertoken",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "revision",
|
||||
"type": "uint64",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "creation_time",
|
||||
"type": "time.Time",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "update_time",
|
||||
"type": "time.Time",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "user_id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "value",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "linkedaccount",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "revision",
|
||||
"type": "uint64",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "creation_time",
|
||||
"type": "time.Time",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "update_time",
|
||||
"type": "time.Time",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "user_id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "remote_user_id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "remote_user_name",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "remote_user_avatar_url",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "remote_source_id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "user_access_token",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "oauth2_access_token",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "oauth2_refresh_token",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "oauth2_access_token_expires_at",
|
||||
"type": "time.Time",
|
||||
"nullable": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "organization",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "revision",
|
||||
"type": "uint64",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "creation_time",
|
||||
"type": "time.Time",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "update_time",
|
||||
"type": "time.Time",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "visibility",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "creator_user_id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "orgmember",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "revision",
|
||||
"type": "uint64",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "creation_time",
|
||||
"type": "time.Time",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "update_time",
|
||||
"type": "time.Time",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "organization_id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "user_id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "member_role",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "projectgroup",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "revision",
|
||||
"type": "uint64",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "creation_time",
|
||||
"type": "time.Time",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "update_time",
|
||||
"type": "time.Time",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "parent_kind",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "parent_id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "visibility",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "project",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "revision",
|
||||
"type": "uint64",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "creation_time",
|
||||
"type": "time.Time",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "update_time",
|
||||
"type": "time.Time",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "parent_kind",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "parent_id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "secret",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "visibility",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "remote_repository_config_type",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "remote_source_id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "linked_account_id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "repository_id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "repository_path",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "ssh_private_key",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "skip_ssh_host_key_check",
|
||||
"type": "bool",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "webhook_secret",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "pass_vars_to_forked_pr",
|
||||
"type": "bool",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "default_branch",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "members_can_perform_run_actions",
|
||||
"type": "bool",
|
||||
"nullable": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "secret",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "revision",
|
||||
"type": "uint64",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "creation_time",
|
||||
"type": "time.Time",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "update_time",
|
||||
"type": "time.Time",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "parent_kind",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "parent_id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "type",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "data",
|
||||
"type": "json",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "secret_provider_id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "path",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "variable",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "revision",
|
||||
"type": "uint64",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "creation_time",
|
||||
"type": "time.Time",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "update_time",
|
||||
"type": "time.Time",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "parent_kind",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "parent_id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "variable_values",
|
||||
"type": "json",
|
||||
"nullable": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "orginvitation",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "revision",
|
||||
"type": "uint64",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "creation_time",
|
||||
"type": "time.Time",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "update_time",
|
||||
"type": "time.Time",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "user_id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "organization_id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "role",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "userprojectfavorite",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "revision",
|
||||
"type": "uint64",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "creation_time",
|
||||
"type": "time.Time",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "update_time",
|
||||
"type": "time.Time",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "user_id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
},
|
||||
{
|
||||
"name": "project_id",
|
||||
"type": "string",
|
||||
"nullable": false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -57,3 +57,7 @@
|
|||
{"exportMeta":{"kind":"OrgInvitation"},"id":"ccfa97b7-f673-4437-9d5f-8fd11ec05c6f","creationTime":"2023-04-07T12:12:19.048529Z","updateTime":"2023-04-07T12:12:19.048529Z","organization_id":"15bfe438-9844-4024-b493-d137468bf6e9","user_id":"06c3b92a-f544-4eab-a254-a9d0465e16fc","role":"owner"}
|
||||
|
||||
{"exportMeta":{"kind":"LinkedAccount"},"id":"4037d8a4-78a2-41dc-8108-faa7f514b5e2","creationTime":"2023-04-07T12:12:19.048529Z","updateTime":"2023-04-07T12:12:19.048529Z","user_id":"06c3b92a-f544-4eab-a254-a9d0465e16fc","remote_user_id":"12345","remote_username":"remoteuser01","remote_source_id":"41e2edca-ed29-4bab-a552-e4720cc2aca9","oauth2_access_token":"accesstoken","oauth_2_access_token_expires_at":"0001-01-01T00:00:00Z"}
|
||||
|
||||
{"exportMeta":{"kind":"UserProjectFavorite"},"id":"6db79d0c-6f75-4212-ac28-9b96ac04db34","creationTime":"2023-04-07T12:12:19.048529Z","updateTime":"2023-04-07T12:12:19.048529Z","user_id":"06c3b92a-f544-4eab-a254-a9d0465e16fc","project_id":"a15977f1-2f25-4fb9-a94c-bdfe11cc7292"}
|
||||
{"exportMeta":{"kind":"UserProjectFavorite"},"id":"72c862b4-4e0c-4877-a326-ff6b60815d32","creationTime":"2023-04-07T12:12:19.048529Z","updateTime":"2023-04-07T12:12:19.048529Z","user_id":"172f750c-0800-4fd1-9eaa-415935cfb7b0","project_id":"ac31830e-af56-4825-882e-a5dedf30ef96"}
|
||||
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
{"table":"remotesource","values":{"id":"41e2edca-ed29-4bab-a552-e4720cc2aca9","creation_time":"2023-04-03T12:23:46.281047451Z","update_time":"2023-04-03T12:23:46.281047451Z","name":"rs01","apiurl":"http://example.com","type":"gitea","auth_type":"password"}}
|
||||
{"table":"user_t","values":{"id":"06c3b92a-f544-4eab-a254-a9d0465e16fc","creation_time":"2023-04-03T12:23:46.281976152Z","update_time":"2023-04-03T12:23:46.281976152Z","name":"user4","secret":"91b63c16455434c6a902625f5729361dd6dbf3a4"}}
|
||||
{"table":"user_t","values":{"id":"172f750c-0800-4fd1-9eaa-415935cfb7b0","creation_time":"2023-04-03T12:23:46.282401495Z","update_time":"2023-04-03T12:23:46.282401495Z","name":"user8","secret":"0184c3cae3ca9b2ab59cb40aa263d135c9f6c381"}}
|
||||
{"table":"user_t","values":{"id":"240ba203-3e26-4451-9018-05c8fee5efc8","creation_time":"2023-04-03T12:23:46.282513244Z","update_time":"2023-04-03T12:23:46.282513244Z","name":"user9","secret":"800a7d79a041c55fa2e456b9d5ddb719fb4d49fa"}}
|
||||
{"table":"user_t","values":{"id":"2a9afa25-f428-4fb7-8fa8-2b530b590ea9","creation_time":"2023-04-03T12:23:46.281399389Z","update_time":"2023-04-03T12:23:46.281399389Z","name":"user0","secret":"f6b12b3faad2e8a8894a45f1a49cea2a87560161"}}
|
||||
{"table":"user_t","values":{"id":"31eb74d4-7bfd-4e28-8de2-a7b75d86b62d","creation_time":"2023-04-03T12:23:51.284329084Z","update_time":"2023-04-03T12:23:51.284329084Z","name":"user13","secret":"ecb7e25dd599cd263bac126999445c45015f1e79"}}
|
||||
{"table":"user_t","values":{"id":"3664b856-f50f-4f66-bb0b-50446e5b6b7d","creation_time":"2023-04-03T12:23:51.285245283Z","update_time":"2023-04-03T12:23:51.285245283Z","name":"user01","secret":"5bb749a35684a7644d3b406672ea4890bee00a4b"}}
|
||||
{"table":"user_t","values":{"id":"3d81312a-4f1c-4795-ab92-55305c6bab72","creation_time":"2023-04-03T12:23:46.281862238Z","update_time":"2023-04-03T12:23:46.281862238Z","name":"user3","secret":"56c45aee5776be4727df920bcb874380f7589282"}}
|
||||
{"table":"user_t","values":{"id":"4b111e2e-aae2-4e74-88ae-0f0bd1b75798","creation_time":"2023-04-03T12:23:51.284008924Z","update_time":"2023-04-03T12:23:51.284008924Z","name":"user11","secret":"ddee8466e21e58b9a96e6e8c659d0fd35532cc8f"}}
|
||||
{"table":"user_t","values":{"id":"5ad2244f-72b8-4b99-90cb-42e0f4906a82","creation_time":"2023-04-03T12:23:46.28206576Z","update_time":"2023-04-03T12:23:46.28206576Z","name":"user5","secret":"3c8671f4206cc744b28380648450c2d074dd114d"}}
|
||||
{"table":"user_t","values":{"id":"6201f121-51b6-4631-bea5-da993c60627e","creation_time":"2023-04-03T12:23:51.28454406Z","update_time":"2023-04-03T12:23:51.28454406Z","name":"user15","secret":"97f1a1c719513072a2872e361a8dbcab4884e322"}}
|
||||
{"table":"user_t","values":{"id":"6220c7c7-b668-46df-bf18-004640a52a71","creation_time":"2023-04-03T12:23:46.282245536Z","update_time":"2023-04-03T12:23:46.282245536Z","name":"user7","secret":"d4f16a8e328b1eae5dafd8a278bf5b14ef1ac308"}}
|
||||
{"table":"user_t","values":{"id":"6a980aa7-7c5c-4274-85d6-06024ddc1bf0","creation_time":"2023-04-03T12:23:51.284652666Z","update_time":"2023-04-03T12:23:51.284652666Z","name":"user16","secret":"1706eb1507c631dbc08c072766e45a61b7d99d6f"}}
|
||||
{"table":"user_t","values":{"id":"6c1bb669-f289-4406-b821-d2a908075c27","creation_time":"2023-04-03T12:23:46.281620372Z","update_time":"2023-04-03T12:23:46.281620372Z","name":"user1","secret":"9376cd24de3e8acf83cb53cff281c7ff57e7faf7"}}
|
||||
{"table":"user_t","values":{"id":"7a19dfb9-023d-4fcb-8661-062c8a35e64e","creation_time":"2023-04-03T12:23:51.28444188Z","update_time":"2023-04-03T12:23:51.28444188Z","name":"user14","secret":"6c63f262db71c6c92c3ffe8a6c371da4d327741b"}}
|
||||
{"table":"user_t","values":{"id":"9b259867-2676-432e-bdc1-d46314069767","creation_time":"2023-04-03T12:23:51.285007258Z","update_time":"2023-04-03T12:23:51.285007258Z","name":"user19","secret":"fa313dc618aea249cf34611526c46777a4926d22"}}
|
||||
{"table":"user_t","values":{"id":"a1d93c42-566a-4f85-b3e9-7808d9c03a8c","creation_time":"2023-04-03T12:23:46.28215928Z","update_time":"2023-04-03T12:23:46.28215928Z","name":"user6","secret":"be3506a311f1b2ff45505b71352bb0ea3652ca83"}}
|
||||
{"table":"user_t","values":{"id":"a1ddc940-0024-4fc6-aa7a-7039dd0219cb","creation_time":"2023-04-03T12:23:51.283685621Z","update_time":"2023-04-03T12:23:51.283685621Z","name":"user10","secret":"a8dfab34e973c9948cc55795eb6f615736e1a724"}}
|
||||
{"table":"user_t","values":{"id":"a5a2935e-6a33-4cb9-99a4-b2924f42eefb","creation_time":"2023-04-03T12:23:46.281783595Z","update_time":"2023-04-03T12:23:46.281783595Z","name":"user2","secret":"851acfde65da1fc57b7d52befb26b2d646525571"}}
|
||||
{"table":"user_t","values":{"id":"a6235238-e63e-4e0d-840c-8428a282c5db","creation_time":"2023-04-03T12:23:51.284905567Z","update_time":"2023-04-03T12:23:51.284905567Z","name":"user18","secret":"e912a8a18940147cf435a417f0cff073e1b9f907"}}
|
||||
{"table":"user_t","values":{"id":"b6f7617a-a5d1-4a63-ad71-b980e82d3a0c","creation_time":"2023-04-03T12:23:51.284182623Z","update_time":"2023-04-03T12:23:51.284182623Z","name":"user12","secret":"75471711fa7214896fe8d3e69ca7f02ac539227a"}}
|
||||
{"table":"user_t","values":{"id":"c9f68e97-15fb-4453-9673-8d1e4ba247b9","creation_time":"2023-04-03T12:23:51.284787253Z","update_time":"2023-04-03T12:23:51.284787253Z","name":"user17","secret":"e8336a917cd4353e9f5bab6e94e770e653d567fb"}}
|
||||
{"table":"organization","values":{"id":"15bfe438-9844-4024-b493-d137468bf6e9","creation_time":"2023-04-03T12:23:51.285377984Z","update_time":"2023-04-03T12:23:51.285377984Z","name":"org01","visibility":"public"}}
|
||||
{"table":"projectgroup","values":{"id":"0316f6cb-1215-4003-823f-4c33abf4f128","creation_time":"2023-04-03T12:23:51.285269658Z","update_time":"2023-04-03T12:23:51.285269658Z","parent_kind":"user","parent_id":"3664b856-f50f-4f66-bb0b-50446e5b6b7d","visibility":"public"}}
|
||||
{"table":"projectgroup","values":{"id":"0988a136-74ac-4da9-be5f-67c7fac4013b","creation_time":"2023-04-03T12:23:51.284207906Z","update_time":"2023-04-03T12:23:51.284207906Z","parent_kind":"user","parent_id":"b6f7617a-a5d1-4a63-ad71-b980e82d3a0c","visibility":"public"}}
|
||||
{"table":"projectgroup","values":{"id":"0cc9b923-ba9d-40d0-abca-0eb381eae08d","creation_time":"2023-04-03T12:23:51.28467285Z","update_time":"2023-04-03T12:23:51.28467285Z","parent_kind":"user","parent_id":"6a980aa7-7c5c-4274-85d6-06024ddc1bf0","visibility":"public"}}
|
||||
{"table":"projectgroup","values":{"id":"0d3c9bc4-ea1d-4750-9c0a-be6e5a2521b7","creation_time":"2023-04-03T12:23:46.282530356Z","update_time":"2023-04-03T12:23:46.282530356Z","parent_kind":"user","parent_id":"240ba203-3e26-4451-9018-05c8fee5efc8","visibility":"public"}}
|
||||
{"table":"projectgroup","values":{"id":"0d6efcb7-0ef4-4b3a-8815-72e3706bf7e5","creation_time":"2023-04-03T12:23:51.286201083Z","update_time":"2023-04-03T12:23:51.286201083Z","name":"projectgroup01","parent_kind":"projectgroup","parent_id":"c6a49dfa-dbfb-43e6-af72-d7d594ed6734","visibility":"public"}}
|
||||
{"table":"projectgroup","values":{"id":"0f26f9cd-31ca-4301-b346-72b7901ecea6","creation_time":"2023-04-03T12:23:46.282420213Z","update_time":"2023-04-03T12:23:46.282420213Z","parent_kind":"user","parent_id":"172f750c-0800-4fd1-9eaa-415935cfb7b0","visibility":"public"}}
|
||||
{"table":"projectgroup","values":{"id":"12ecac96-fd68-46e4-a458-e3c1acf3ae04","creation_time":"2023-04-03T12:23:46.28208378Z","update_time":"2023-04-03T12:23:46.28208378Z","parent_kind":"user","parent_id":"5ad2244f-72b8-4b99-90cb-42e0f4906a82","visibility":"public"}}
|
||||
{"table":"projectgroup","values":{"id":"37795e36-163e-4368-9681-fc8b8d8caa3e","creation_time":"2023-04-03T12:23:51.285027862Z","update_time":"2023-04-03T12:23:51.285027862Z","parent_kind":"user","parent_id":"9b259867-2676-432e-bdc1-d46314069767","visibility":"public"}}
|
||||
{"table":"projectgroup","values":{"id":"421cec99-5434-46da-9421-43bf1ad3e24d","creation_time":"2023-04-03T12:23:51.28403714Z","update_time":"2023-04-03T12:23:51.28403714Z","parent_kind":"user","parent_id":"4b111e2e-aae2-4e74-88ae-0f0bd1b75798","visibility":"public"}}
|
||||
{"table":"projectgroup","values":{"id":"42f8fb71-56a1-4584-94d9-074a4730f295","creation_time":"2023-04-03T12:23:51.284560264Z","update_time":"2023-04-03T12:23:51.284560264Z","parent_kind":"user","parent_id":"6201f121-51b6-4631-bea5-da993c60627e","visibility":"public"}}
|
||||
{"table":"projectgroup","values":{"id":"4f2568d5-7d78-4268-81a7-f49edef85fad","creation_time":"2023-04-03T12:23:51.285854313Z","update_time":"2023-04-03T12:23:51.285854313Z","name":"projectgroup01","parent_kind":"projectgroup","parent_id":"0316f6cb-1215-4003-823f-4c33abf4f128","visibility":"public"}}
|
||||
{"table":"projectgroup","values":{"id":"54dac4ed-a596-447b-bd85-5c987d3878b6","creation_time":"2023-04-03T12:23:46.281893179Z","update_time":"2023-04-03T12:23:46.281893179Z","parent_kind":"user","parent_id":"3d81312a-4f1c-4795-ab92-55305c6bab72","visibility":"public"}}
|
||||
{"table":"projectgroup","values":{"id":"6c4a38dd-13ef-4810-915b-f7584f5cc320","creation_time":"2023-04-03T12:23:46.28143899Z","update_time":"2023-04-03T12:23:46.28143899Z","parent_kind":"user","parent_id":"2a9afa25-f428-4fb7-8fa8-2b530b590ea9","visibility":"public"}}
|
||||
{"table":"projectgroup","values":{"id":"6d91e71e-0dfd-4f87-a2aa-86d3abd84034","creation_time":"2023-04-03T12:23:51.284805971Z","update_time":"2023-04-03T12:23:51.284805971Z","parent_kind":"user","parent_id":"c9f68e97-15fb-4453-9673-8d1e4ba247b9","visibility":"public"}}
|
||||
{"table":"projectgroup","values":{"id":"8b8f07d1-1078-4e3c-af4a-36f6cab55ab3","creation_time":"2023-04-03T12:23:46.281996826Z","update_time":"2023-04-03T12:23:46.281996826Z","parent_kind":"user","parent_id":"06c3b92a-f544-4eab-a254-a9d0465e16fc","visibility":"public"}}
|
||||
{"table":"projectgroup","values":{"id":"8ce0fdc5-0356-4565-b721-9022c47999c0","creation_time":"2023-04-03T12:23:46.281662278Z","update_time":"2023-04-03T12:23:46.281662278Z","parent_kind":"user","parent_id":"6c1bb669-f289-4406-b821-d2a908075c27","visibility":"public"}}
|
||||
{"table":"projectgroup","values":{"id":"911a177f-1f3e-4277-b2c4-3269906135cc","creation_time":"2023-04-03T12:23:51.284356322Z","update_time":"2023-04-03T12:23:51.284356322Z","parent_kind":"user","parent_id":"31eb74d4-7bfd-4e28-8de2-a7b75d86b62d","visibility":"public"}}
|
||||
{"table":"projectgroup","values":{"id":"92689b70-bbf4-43f5-b481-e60a955fe934","creation_time":"2023-04-03T12:23:46.282262648Z","update_time":"2023-04-03T12:23:46.282262648Z","parent_kind":"user","parent_id":"6220c7c7-b668-46df-bf18-004640a52a71","visibility":"public"}}
|
||||
{"table":"projectgroup","values":{"id":"a4a944f8-f43b-4ab9-a3c3-83d1e5d97eca","creation_time":"2023-04-03T12:23:51.284923237Z","update_time":"2023-04-03T12:23:51.284923237Z","parent_kind":"user","parent_id":"a6235238-e63e-4e0d-840c-8428a282c5db","visibility":"public"}}
|
||||
{"table":"projectgroup","values":{"id":"c6a49dfa-dbfb-43e6-af72-d7d594ed6734","creation_time":"2023-04-03T12:23:51.285403617Z","update_time":"2023-04-03T12:23:51.285403617Z","parent_kind":"org","parent_id":"15bfe438-9844-4024-b493-d137468bf6e9","visibility":"public"}}
|
||||
{"table":"projectgroup","values":{"id":"e3ce2f10-4766-49a4-ace4-9867014eb2f2","creation_time":"2023-04-03T12:23:46.282174436Z","update_time":"2023-04-03T12:23:46.282174436Z","parent_kind":"user","parent_id":"a1d93c42-566a-4f85-b3e9-7808d9c03a8c","visibility":"public"}}
|
||||
{"table":"projectgroup","values":{"id":"e76c2e8d-b33c-49ab-8c7b-efe401693f6e","creation_time":"2023-04-03T12:23:51.283740308Z","update_time":"2023-04-03T12:23:51.283740308Z","parent_kind":"user","parent_id":"a1ddc940-0024-4fc6-aa7a-7039dd0219cb","visibility":"public"}}
|
||||
{"table":"projectgroup","values":{"id":"f0c12a1c-ffca-446d-b35f-4e1c650bf3e5","creation_time":"2023-04-03T12:23:51.284460109Z","update_time":"2023-04-03T12:23:51.284460109Z","parent_kind":"user","parent_id":"7a19dfb9-023d-4fcb-8661-062c8a35e64e","visibility":"public"}}
|
||||
{"table":"projectgroup","values":{"id":"f7b239bf-2a75-464e-8a47-340299bbbbc2","creation_time":"2023-04-03T12:23:46.28179924Z","update_time":"2023-04-03T12:23:46.28179924Z","parent_kind":"user","parent_id":"a5a2935e-6a33-4cb9-99a4-b2924f42eefb","visibility":"public"}}
|
||||
{"table":"project","values":{"id":"a15977f1-2f25-4fb9-a94c-bdfe11cc7292","creation_time":"2023-04-03T12:23:51.285619501Z","update_time":"2023-04-03T12:23:51.285619501Z","name":"project01","parent_kind":"projectgroup","parent_id":"0316f6cb-1215-4003-823f-4c33abf4f128","secret":"1de077c9d0a18ea0543aa58c7bc44646c4a62349","visibility":"public","remote_repository_config_type":"manual","webhook_secret":"df258d355846073b83754824c5b4142155b5ef28","members_can_perform_run_actions":false}}
|
||||
{"table":"project","values":{"id":"ac31830e-af56-4825-882e-a5dedf30ef96","creation_time":"2023-04-03T12:23:51.286053365Z","update_time":"2023-04-03T12:23:51.286053365Z","name":"project01","parent_kind":"projectgroup","parent_id":"4f2568d5-7d78-4268-81a7-f49edef85fad","secret":"338046e8570ba381cd54ef3089f484bc28c52fed","visibility":"public","remote_repository_config_type":"manual","webhook_secret":"d364a30958a3319ea21cc153ed529d1a77cd6411","members_can_perform_run_actions":false}}
|
||||
{"table":"secret","values":{"id":"7489c8d6-a91e-4f7e-97f0-add1d81671a3","creation_time":"2023-04-03T12:23:51.286411031Z","update_time":"2023-04-03T12:23:51.286411031Z","name":"secret01","parent_kind":"project","parent_id":"ac31830e-af56-4825-882e-a5dedf30ef96","type":"internal","data":{"secret01":"secretvar01"}}}
|
||||
{"table":"variable","values":{"id":"8faedc8f-9b3c-4403-9b5c-f20193a33817","creation_time":"2023-04-03T12:23:51.287368857Z","update_time":"2023-04-03T12:23:51.287368857Z","name":"variable01","parent_kind":"projectgroup","parent_id":"4f2568d5-7d78-4268-81a7-f49edef85fad","variable_values":[{"secret_name":"secret01","secret_var":"secretvar01"}]}}
|
||||
|
||||
{"table":"usertoken","values":{"id":"380b36a3-c860-4540-89b1-99a0708eac58","creation_time":"2023-04-07T12:12:19.048529Z","update_time":"2023-04-07T12:12:19.048529Z","name":"default","value":"tokenvalue","user_id":"06c3b92a-f544-4eab-a254-a9d0465e16fc"}}
|
||||
|
||||
{"table":"orgmember","values":{"id":"8749225d-5356-4c15-a14a-986a21e06498","creation_time":"2023-04-07T12:12:19.048529Z","update_time":"2023-04-07T12:12:19.048529Z","organization_id":"15bfe438-9844-4024-b493-d137468bf6e9","user_id":"06c3b92a-f544-4eab-a254-a9d0465e16fc","member_role":"owner"}}
|
||||
|
||||
{"table":"orginvitation","values":{"id":"ccfa97b7-f673-4437-9d5f-8fd11ec05c6f","creation_time":"2023-04-07T12:12:19.048529Z","update_time":"2023-04-07T12:12:19.048529Z","organization_id":"15bfe438-9844-4024-b493-d137468bf6e9","user_id":"06c3b92a-f544-4eab-a254-a9d0465e16fc","role":"owner"}}
|
||||
|
||||
{"table":"linkedaccount","values":{"id":"4037d8a4-78a2-41dc-8108-faa7f514b5e2","creation_time":"2023-04-07T12:12:19.048529Z","update_time":"2023-04-07T12:12:19.048529Z","user_id":"06c3b92a-f544-4eab-a254-a9d0465e16fc","remote_user_id":"12345","remote_user_name":"remoteuser01","remote_source_id":"41e2edca-ed29-4bab-a552-e4720cc2aca9","oauth2_access_token":"accesstoken","oauth2_access_token_expires_at":"0001-01-01T00:00:00Z"}}
|
|
@ -36,6 +36,7 @@ var importFixtures = testutil.DataFixtures{
|
|||
1: "dbv1.jsonc",
|
||||
2: "dbv2.jsonc",
|
||||
3: "dbv3.jsonc",
|
||||
4: "dbv4.jsonc",
|
||||
}
|
||||
|
||||
func TestCreate(t *testing.T) {
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
// Copyright 2019 Sorint.lab
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package action
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/sorintlab/errors"
|
||||
|
||||
"agola.io/agola/internal/services/gateway/common"
|
||||
"agola.io/agola/internal/util"
|
||||
csapitypes "agola.io/agola/services/configstore/api/types"
|
||||
"agola.io/agola/services/configstore/client"
|
||||
cstypes "agola.io/agola/services/configstore/types"
|
||||
)
|
||||
|
||||
type CreateUserProjectFavoriteRequest struct {
|
||||
ProjectRef string
|
||||
}
|
||||
|
||||
func (h *ActionHandler) CreateUserProjectFavorite(ctx context.Context, req *CreateUserProjectFavoriteRequest) (*cstypes.UserProjectFavorite, error) {
|
||||
if !common.IsUserLogged(ctx) {
|
||||
return nil, errors.Errorf("user not logged in")
|
||||
}
|
||||
|
||||
userID := common.CurrentUserID(ctx)
|
||||
|
||||
creq := &csapitypes.CreateUserProjectFavoriteRequest{
|
||||
UserRef: userID,
|
||||
ProjectRef: req.ProjectRef,
|
||||
}
|
||||
|
||||
userProjectFavorite, _, err := h.configstoreClient.CreateUserProjectFavorite(ctx, creq)
|
||||
if err != nil {
|
||||
return nil, util.NewAPIError(util.KindFromRemoteError(err), errors.Wrapf(err, "failed to create user project favorite"))
|
||||
}
|
||||
|
||||
return userProjectFavorite, nil
|
||||
}
|
||||
|
||||
func (h *ActionHandler) DeleteUserProjectFavorite(ctx context.Context, projectRef string) error {
|
||||
if !common.IsUserLogged(ctx) {
|
||||
return errors.Errorf("user not logged in")
|
||||
}
|
||||
|
||||
userID := common.CurrentUserID(ctx)
|
||||
|
||||
if _, err := h.configstoreClient.DeleteUserProjectFavorite(ctx, userID, projectRef); err != nil {
|
||||
return util.NewAPIError(util.KindFromRemoteError(err), errors.Wrapf(err, "failed to delete user project favorite"))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type GetUserProjectFavoritesRequest struct {
|
||||
Cursor string
|
||||
|
||||
Limit int
|
||||
SortDirection SortDirection
|
||||
}
|
||||
|
||||
type GetUserProjectFavoritesResponse struct {
|
||||
UserProjectFavorites []*cstypes.UserProjectFavorite
|
||||
Cursor string
|
||||
}
|
||||
|
||||
func (h *ActionHandler) GetUserProjectFavorites(ctx context.Context, req *GetUserProjectFavoritesRequest) (*GetUserProjectFavoritesResponse, error) {
|
||||
if !common.IsUserLogged(ctx) {
|
||||
return nil, errors.Errorf("user not logged in")
|
||||
}
|
||||
userID := common.CurrentUserID(ctx)
|
||||
|
||||
inCursor := &StartCursor{}
|
||||
sortDirection := req.SortDirection
|
||||
if req.Cursor != "" {
|
||||
if err := UnmarshalCursor(req.Cursor, inCursor); err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
sortDirection = inCursor.SortDirection
|
||||
}
|
||||
if sortDirection == "" {
|
||||
sortDirection = SortDirectionAsc
|
||||
}
|
||||
|
||||
userProjectFavorites, resp, err := h.configstoreClient.GetUserProjectFavorites(ctx, userID, &client.GetUserProjectFavoritesOptions{ListOptions: &client.ListOptions{Limit: req.Limit, SortDirection: cstypes.SortDirection(sortDirection)}, StartUserProjectFavoriteID: inCursor.Start})
|
||||
if err != nil {
|
||||
return nil, util.NewAPIError(util.KindFromRemoteError(err), err)
|
||||
}
|
||||
|
||||
var outCursor string
|
||||
if resp.HasMore && len(userProjectFavorites) > 0 {
|
||||
lastuserProjectFavoriteID := userProjectFavorites[len(userProjectFavorites)-1].ID
|
||||
outCursor, err = MarshalCursor(&StartCursor{
|
||||
Start: lastuserProjectFavoriteID,
|
||||
SortDirection: sortDirection,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
}
|
||||
|
||||
res := &GetUserProjectFavoritesResponse{
|
||||
UserProjectFavorites: userProjectFavorites,
|
||||
Cursor: outCursor,
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
// Copyright 2024 Sorint.lab
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/sorintlab/errors"
|
||||
|
||||
"agola.io/agola/internal/services/gateway/action"
|
||||
util "agola.io/agola/internal/util"
|
||||
cstypes "agola.io/agola/services/configstore/types"
|
||||
gwapitypes "agola.io/agola/services/gateway/api/types"
|
||||
)
|
||||
|
||||
type CreateUserProjectFavoriteHandler struct {
|
||||
log zerolog.Logger
|
||||
ah *action.ActionHandler
|
||||
}
|
||||
|
||||
func NewCreateUserProjectFavoriteHandler(log zerolog.Logger, ah *action.ActionHandler) *CreateUserProjectFavoriteHandler {
|
||||
return &CreateUserProjectFavoriteHandler{log: log, ah: ah}
|
||||
}
|
||||
|
||||
func (h *CreateUserProjectFavoriteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
vars := mux.Vars(r)
|
||||
|
||||
projectRef := vars["projectref"]
|
||||
|
||||
creq := &action.CreateUserProjectFavoriteRequest{
|
||||
ProjectRef: projectRef,
|
||||
}
|
||||
|
||||
userProjectFavorite, err := h.ah.CreateUserProjectFavorite(ctx, creq)
|
||||
if util.HTTPError(w, err) {
|
||||
h.log.Err(err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
if err := util.HTTPResponse(w, http.StatusCreated, userProjectFavorite); err != nil {
|
||||
h.log.Err(err).Send()
|
||||
}
|
||||
}
|
||||
|
||||
type DeleteUserProjectFavoriteHandler struct {
|
||||
log zerolog.Logger
|
||||
ah *action.ActionHandler
|
||||
}
|
||||
|
||||
func NewDeleteUserProjectFavoriteHandler(log zerolog.Logger, ah *action.ActionHandler) *DeleteUserProjectFavoriteHandler {
|
||||
return &DeleteUserProjectFavoriteHandler{log: log, ah: ah}
|
||||
}
|
||||
|
||||
func (h *DeleteUserProjectFavoriteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
vars := mux.Vars(r)
|
||||
|
||||
projectRef := vars["projectref"]
|
||||
|
||||
err := h.ah.DeleteUserProjectFavorite(ctx, projectRef)
|
||||
if util.HTTPError(w, err) {
|
||||
h.log.Err(err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
if err := util.HTTPResponse(w, http.StatusNoContent, nil); err != nil {
|
||||
h.log.Err(err).Send()
|
||||
}
|
||||
}
|
||||
|
||||
type UserProjectFavoritesHandler struct {
|
||||
log zerolog.Logger
|
||||
ah *action.ActionHandler
|
||||
}
|
||||
|
||||
func NewUserProjectFavoritesHandler(log zerolog.Logger, ah *action.ActionHandler) *UserProjectFavoritesHandler {
|
||||
return &UserProjectFavoritesHandler{log: log, ah: ah}
|
||||
}
|
||||
|
||||
func (h *UserProjectFavoritesHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
res, err := h.do(w, r)
|
||||
if util.HTTPError(w, err) {
|
||||
h.log.Err(err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
if err := util.HTTPResponse(w, http.StatusOK, res); err != nil {
|
||||
h.log.Err(err).Send()
|
||||
}
|
||||
}
|
||||
|
||||
func (h *UserProjectFavoritesHandler) do(w http.ResponseWriter, r *http.Request) ([]*gwapitypes.UserProjectFavoriteResponse, error) {
|
||||
ctx := r.Context()
|
||||
|
||||
ropts, err := parseRequestOptions(r)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
ares, err := h.ah.GetUserProjectFavorites(ctx, &action.GetUserProjectFavoritesRequest{Cursor: ropts.Cursor, Limit: ropts.Limit, SortDirection: action.SortDirection(ropts.SortDirection)})
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
userProjectFavorites := make([]*gwapitypes.UserProjectFavoriteResponse, len(ares.UserProjectFavorites))
|
||||
for i, p := range ares.UserProjectFavorites {
|
||||
userProjectFavorites[i] = createUserProjectFavoriteResponse(p)
|
||||
}
|
||||
|
||||
addCursorHeader(w, ares.Cursor)
|
||||
|
||||
return userProjectFavorites, nil
|
||||
}
|
||||
|
||||
func createUserProjectFavoriteResponse(o *cstypes.UserProjectFavorite) *gwapitypes.UserProjectFavoriteResponse {
|
||||
org := &gwapitypes.UserProjectFavoriteResponse{
|
||||
ID: o.ID,
|
||||
ProjectID: o.ProjectID,
|
||||
}
|
||||
return org
|
||||
}
|
|
@ -265,6 +265,10 @@ func (g *Gateway) Run(ctx context.Context) error {
|
|||
userRunLogsHandler := api.NewLogsHandler(g.log, g.ah, scommon.GroupTypeUser)
|
||||
userRunLogsDeleteHandler := api.NewLogsDeleteHandler(g.log, g.ah, scommon.GroupTypeUser)
|
||||
|
||||
createUserProjectFavoriteHandler := api.NewCreateUserProjectFavoriteHandler(g.log, g.ah)
|
||||
deleteUserProjectFavoriteHandler := api.NewDeleteUserProjectFavoriteHandler(g.log, g.ah)
|
||||
userProjectFavoritesHandler := api.NewUserProjectFavoritesHandler(g.log, g.ah)
|
||||
|
||||
userRemoteReposHandler := api.NewUserRemoteReposHandler(g.log, g.ah, g.configstoreClient)
|
||||
|
||||
badgeHandler := api.NewBadgeHandler(g.log, g.ah)
|
||||
|
@ -354,6 +358,9 @@ func (g *Gateway) Run(ctx context.Context) error {
|
|||
apirouter.Handle("/user/orgs", authForcedHandler(userOrgsHandler)).Methods("GET")
|
||||
apirouter.Handle("/user/org_invitations", authForcedHandler(userOrgInvitationsHandler)).Methods("GET")
|
||||
apirouter.Handle("/user/org_invitations/{orgref}/actions", authForcedHandler(userOrgInvitationActionHandler)).Methods("PUT")
|
||||
apirouter.Handle("/user/projects/{projectref}/projectfavorites", authForcedHandler(createUserProjectFavoriteHandler)).Methods("POST")
|
||||
apirouter.Handle("/user/projects/{projectref}/projectfavorites", authForcedHandler(deleteUserProjectFavoriteHandler)).Methods("DELETE")
|
||||
apirouter.Handle("/user/projectfavorites", authForcedHandler(userProjectFavoritesHandler)).Methods("GET")
|
||||
|
||||
apirouter.Handle("/users/{userref}/runs", authForcedHandler(userRunsHandler)).Methods("GET")
|
||||
apirouter.Handle("/users/{userref}/runs/{runnumber}", authOptionalHandler(userRunHandler)).Methods("GET")
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright 2024 Sorint.lab
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package types
|
||||
|
||||
type CreateUserProjectFavoriteRequest struct {
|
||||
UserRef string
|
||||
ProjectRef string
|
||||
}
|
|
@ -778,3 +778,42 @@ func (c *Client) Import(ctx context.Context, r io.Reader) (*Response, error) {
|
|||
resp, err := c.GetResponse(ctx, "POST", "/import", nil, -1, common.JSONContent, r)
|
||||
return resp, errors.WithStack(err)
|
||||
}
|
||||
|
||||
func (c *Client) CreateUserProjectFavorite(ctx context.Context, req *csapitypes.CreateUserProjectFavoriteRequest) (*cstypes.UserProjectFavorite, *Response, error) {
|
||||
reqj, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
return nil, nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
userProjectFavorite := new(cstypes.UserProjectFavorite)
|
||||
resp, err := c.GetParsedResponse(ctx, "POST", fmt.Sprintf("/users/%s/projects/%s/projectfavorites", req.UserRef, req.ProjectRef), nil, common.JSONContent, bytes.NewReader(reqj), userProjectFavorite)
|
||||
return userProjectFavorite, resp, errors.WithStack(err)
|
||||
}
|
||||
|
||||
func (c *Client) DeleteUserProjectFavorite(ctx context.Context, userRef string, projectRef string) (*Response, error) {
|
||||
resp, err := c.GetResponse(ctx, "DELETE", fmt.Sprintf("/users/%s/projects/%s/projectfavorites", userRef, projectRef), nil, -1, common.JSONContent, nil)
|
||||
return resp, errors.WithStack(err)
|
||||
}
|
||||
|
||||
type GetUserProjectFavoritesOptions struct {
|
||||
*ListOptions
|
||||
|
||||
StartUserProjectFavoriteID string
|
||||
}
|
||||
|
||||
func (o *GetUserProjectFavoritesOptions) Add(q url.Values) {
|
||||
o.ListOptions.Add(q)
|
||||
|
||||
if o.StartUserProjectFavoriteID != "" {
|
||||
q.Add("startuserprojectfavoriteid", o.StartUserProjectFavoriteID)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) GetUserProjectFavorites(ctx context.Context, userRef string, opts *GetUserProjectFavoritesOptions) ([]*cstypes.UserProjectFavorite, *Response, error) {
|
||||
q := url.Values{}
|
||||
opts.Add(q)
|
||||
|
||||
userProjectFavorites := []*cstypes.UserProjectFavorite{}
|
||||
resp, err := c.GetParsedResponse(ctx, "GET", fmt.Sprintf("/users/%s/projectfavorites", userRef), q, common.JSONContent, nil, &userProjectFavorites)
|
||||
return userProjectFavorites, resp, errors.WithStack(err)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright 2024 Sorint.lab
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"agola.io/agola/internal/sqlg"
|
||||
"agola.io/agola/internal/sqlg/sql"
|
||||
)
|
||||
|
||||
type UserProjectFavorite struct {
|
||||
sqlg.ObjectMeta
|
||||
|
||||
UserID string `json:"user_id,omitempty"`
|
||||
|
||||
ProjectID string `json:"project_id,omitempty"`
|
||||
}
|
||||
|
||||
func NewUserProjectFavorite(tx *sql.Tx) *UserProjectFavorite {
|
||||
return &UserProjectFavorite{
|
||||
ObjectMeta: sqlg.NewObjectMeta(tx),
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package types
|
||||
|
||||
type UserProjectFavoriteResponse struct {
|
||||
ID string `json:"id"`
|
||||
ProjectID string `json:"project_id"`
|
||||
}
|
||||
|
||||
type CreateUserProjectFavoriteRequest struct {
|
||||
ProjectRef string
|
||||
}
|
|
@ -871,3 +871,27 @@ func (c *Client) GetProjectCommitStatusDeliveries(ctx context.Context, projectRe
|
|||
func (c *Client) ProjectCommitStatusRedelivery(ctx context.Context, projectRef string, commitStatusDeliveryID string) (*Response, error) {
|
||||
return c.getResponse(ctx, "PUT", fmt.Sprintf("/projects/%s/commitstatusdeliveries/%s/redelivery", url.PathEscape(projectRef), commitStatusDeliveryID), nil, jsonContent, nil)
|
||||
}
|
||||
|
||||
func (c *Client) GetUserProjectFavorites(ctx context.Context, opts *ListOptions) ([]*gwapitypes.UserProjectFavoriteResponse, *Response, error) {
|
||||
q := url.Values{}
|
||||
opts.Add(q)
|
||||
|
||||
projectFavorites := []*gwapitypes.UserProjectFavoriteResponse{}
|
||||
resp, err := c.getParsedResponse(ctx, "GET", "/user/projectfavorites", q, jsonContent, nil, &projectFavorites)
|
||||
return projectFavorites, resp, errors.WithStack(err)
|
||||
}
|
||||
|
||||
func (c *Client) CreateUserProjectFavorite(ctx context.Context, req *gwapitypes.CreateUserProjectFavoriteRequest) (*gwapitypes.UserProjectFavoriteResponse, *Response, error) {
|
||||
reqj, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
return nil, nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
projectFavorite := new(gwapitypes.UserProjectFavoriteResponse)
|
||||
resp, err := c.getParsedResponse(ctx, "POST", fmt.Sprintf("/user/projects/%s/projectfavorites", req.ProjectRef), nil, jsonContent, bytes.NewReader(reqj), projectFavorite)
|
||||
return projectFavorite, resp, errors.WithStack(err)
|
||||
}
|
||||
|
||||
func (c *Client) DeleteUserProjectFavorite(ctx context.Context, projectRef string) (*Response, error) {
|
||||
return c.getResponse(ctx, "DELETE", fmt.Sprintf("/user/projects/%s/projectfavorites", projectRef), nil, jsonContent, nil)
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"path"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"sort"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -3585,3 +3586,327 @@ func testGetGroupRuns(t *testing.T, userRun bool) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
type userProjectFavoritesByID []*gwapitypes.UserProjectFavoriteResponse
|
||||
|
||||
func (p userProjectFavoritesByID) Len() int { return len(p) }
|
||||
func (p userProjectFavoritesByID) Less(i, j int) bool {
|
||||
return p[i].ID < p[j].ID
|
||||
}
|
||||
func (p userProjectFavoritesByID) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
||||
|
||||
func TestUserProjectFavorite(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
type testUserProjectFavoriteConfig struct {
|
||||
sc *setupContext
|
||||
tokenUser01 string
|
||||
tokenUser02 string
|
||||
gwAdminClient *gwclient.Client
|
||||
gwClientUser01 *gwclient.Client
|
||||
gwClientUser02 *gwclient.Client
|
||||
projects []*gwapitypes.ProjectResponse
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
f func(ctx context.Context, t *testing.T, tc *testUserProjectFavoriteConfig)
|
||||
}{
|
||||
{
|
||||
name: "create user project favorite",
|
||||
f: func(ctx context.Context, t *testing.T, tc *testUserProjectFavoriteConfig) {
|
||||
var expectedUser01ProjectFavorites []*gwapitypes.UserProjectFavoriteResponse
|
||||
var expectedUser02ProjectFavorites []*gwapitypes.UserProjectFavoriteResponse
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
projectFavorite, _, err := tc.gwClientUser01.CreateUserProjectFavorite(ctx, &gwapitypes.CreateUserProjectFavoriteRequest{ProjectRef: tc.projects[i].ID})
|
||||
testutil.NilError(t, err)
|
||||
|
||||
expectedUser01ProjectFavorites = append(expectedUser01ProjectFavorites, projectFavorite)
|
||||
}
|
||||
sort.Sort(userProjectFavoritesByID(expectedUser01ProjectFavorites))
|
||||
|
||||
for i := 2; i < 4; i++ {
|
||||
userProjectFavorite, _, err := tc.gwClientUser02.CreateUserProjectFavorite(ctx, &gwapitypes.CreateUserProjectFavoriteRequest{ProjectRef: tc.projects[i].ID})
|
||||
testutil.NilError(t, err)
|
||||
|
||||
expectedUser02ProjectFavorites = append(expectedUser02ProjectFavorites, userProjectFavorite)
|
||||
}
|
||||
sort.Sort(userProjectFavoritesByID(expectedUser02ProjectFavorites))
|
||||
|
||||
userProjectFavorites, _, err := tc.gwClientUser01.GetUserProjectFavorites(ctx, nil)
|
||||
testutil.NilError(t, err)
|
||||
assert.DeepEqual(t, userProjectFavorites, expectedUser01ProjectFavorites)
|
||||
|
||||
userProjectFavorites, _, err = tc.gwClientUser02.GetUserProjectFavorites(ctx, nil)
|
||||
testutil.NilError(t, err)
|
||||
assert.DeepEqual(t, userProjectFavorites, expectedUser02ProjectFavorites)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "test user project favorite creation with already existing project favorite",
|
||||
f: func(ctx context.Context, t *testing.T, tc *testUserProjectFavoriteConfig) {
|
||||
userProjectFavorite, _, err := tc.gwClientUser01.CreateUserProjectFavorite(ctx, &gwapitypes.CreateUserProjectFavoriteRequest{ProjectRef: tc.projects[0].ID})
|
||||
testutil.NilError(t, err)
|
||||
|
||||
_, _, err = tc.gwClientUser01.CreateUserProjectFavorite(ctx, &gwapitypes.CreateUserProjectFavoriteRequest{ProjectRef: tc.projects[0].ID})
|
||||
expectedErr := remoteErrorBadRequest
|
||||
assert.Error(t, err, expectedErr)
|
||||
|
||||
userProjectFavorites, _, err := tc.gwClientUser01.GetUserProjectFavorites(ctx, nil)
|
||||
testutil.NilError(t, err)
|
||||
assert.Assert(t, cmp.Equal(len(userProjectFavorites), 1))
|
||||
assert.DeepEqual(t, userProjectFavorites[0], userProjectFavorite)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "test user project favorite creation with not existing project",
|
||||
f: func(ctx context.Context, t *testing.T, tc *testUserProjectFavoriteConfig) {
|
||||
_, _, err := tc.gwClientUser01.CreateUserProjectFavorite(ctx, &gwapitypes.CreateUserProjectFavoriteRequest{ProjectRef: "projecttest"})
|
||||
expectedErr := remoteErrorBadRequest
|
||||
assert.Error(t, err, expectedErr)
|
||||
|
||||
userProjectFavorites, _, err := tc.gwClientUser01.GetUserProjectFavorites(ctx, nil)
|
||||
testutil.NilError(t, err)
|
||||
assert.Assert(t, cmp.Equal(len(userProjectFavorites), 0))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "test user project favorite deletion",
|
||||
f: func(ctx context.Context, t *testing.T, tc *testUserProjectFavoriteConfig) {
|
||||
_, _, err := tc.gwClientUser01.CreateUserProjectFavorite(ctx, &gwapitypes.CreateUserProjectFavoriteRequest{ProjectRef: tc.projects[0].ID})
|
||||
testutil.NilError(t, err)
|
||||
|
||||
_, err = tc.gwClientUser01.DeleteUserProjectFavorite(ctx, tc.projects[0].ID)
|
||||
testutil.NilError(t, err)
|
||||
|
||||
userProjectFavorites, _, err := tc.gwClientUser01.GetUserProjectFavorites(ctx, nil)
|
||||
testutil.NilError(t, err)
|
||||
assert.Assert(t, cmp.Equal(len(userProjectFavorites), 0))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "test user project favorite deletion with not existing project favorite",
|
||||
f: func(ctx context.Context, t *testing.T, tc *testUserProjectFavoriteConfig) {
|
||||
_, err := tc.gwClientUser01.DeleteUserProjectFavorite(ctx, tc.projects[0].ID)
|
||||
expectedErr := remoteErrorBadRequest
|
||||
assert.Error(t, err, expectedErr)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "test user project deletion with existing project favorite",
|
||||
f: func(ctx context.Context, t *testing.T, tc *testUserProjectFavoriteConfig) {
|
||||
_, _, err := tc.gwClientUser01.CreateUserProjectFavorite(ctx, &gwapitypes.CreateUserProjectFavoriteRequest{ProjectRef: tc.projects[0].ID})
|
||||
testutil.NilError(t, err)
|
||||
|
||||
_, err = tc.gwClientUser01.DeleteProject(ctx, tc.projects[0].ID)
|
||||
testutil.NilError(t, err)
|
||||
|
||||
userProjectFavorites, _, err := tc.gwClientUser01.GetUserProjectFavorites(ctx, nil)
|
||||
testutil.NilError(t, err)
|
||||
assert.Assert(t, cmp.Equal(len(userProjectFavorites), 0))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "test get user project preferites with admin user",
|
||||
f: func(ctx context.Context, t *testing.T, tc *testUserProjectFavoriteConfig) {
|
||||
_, _, err := tc.gwAdminClient.GetUserProjectFavorites(ctx, nil)
|
||||
expectedErr := remoteErrorInternal
|
||||
assert.Error(t, err, expectedErr)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
dir := t.TempDir()
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
sc := setup(ctx, t, dir, withGitea(true))
|
||||
defer sc.stop()
|
||||
|
||||
gwAdminClient := gwclient.NewClient(sc.config.Gateway.APIExposedURL, sc.config.Gateway.AdminToken)
|
||||
|
||||
giteaToken, tokenUser01 := createLinkedAccount(ctx, t, sc.gitea, sc.config)
|
||||
gwClientUser01 := gwclient.NewClient(sc.config.Gateway.APIExposedURL, tokenUser01)
|
||||
|
||||
_, _, err := gwAdminClient.CreateUser(ctx, &gwapitypes.CreateUserRequest{UserName: agolaUser02})
|
||||
testutil.NilError(t, err)
|
||||
|
||||
tokenUser02, _, err := gwAdminClient.CreateUserToken(ctx, agolaUser02, &gwapitypes.CreateUserTokenRequest{TokenName: "test"})
|
||||
testutil.NilError(t, err)
|
||||
|
||||
gwClientUser02 := gwclient.NewClient(sc.config.Gateway.APIExposedURL, tokenUser02.Token)
|
||||
|
||||
_, _, err = gwClientUser01.CreateOrg(ctx, &gwapitypes.CreateOrgRequest{Name: agolaOrg01, Visibility: gwapitypes.VisibilityPublic})
|
||||
testutil.NilError(t, err)
|
||||
|
||||
giteaAPIURL := fmt.Sprintf("http://%s:%s", sc.gitea.HTTPListenAddress, sc.gitea.HTTPPort)
|
||||
|
||||
giteaClient, err := gitea.NewClient(giteaAPIURL, gitea.SetToken(giteaToken))
|
||||
testutil.NilError(t, err)
|
||||
|
||||
var projects []*gwapitypes.ProjectResponse
|
||||
|
||||
_, project := createProject(ctx, t, giteaClient, gwClientUser01, withVisibility(gwapitypes.VisibilityPrivate))
|
||||
projects = append(projects, project)
|
||||
|
||||
for i := 2; i < 5; i++ {
|
||||
project, _, err = gwClientUser01.CreateProject(ctx, &gwapitypes.CreateProjectRequest{
|
||||
Name: fmt.Sprintf("project0%d", i),
|
||||
ParentRef: path.Join("org", agolaOrg01),
|
||||
RemoteSourceName: "gitea",
|
||||
RepoPath: path.Join(giteaUser01, "repo01"),
|
||||
Visibility: gwapitypes.VisibilityPublic,
|
||||
})
|
||||
testutil.NilError(t, err)
|
||||
|
||||
projects = append(projects, project)
|
||||
}
|
||||
|
||||
tc := &testUserProjectFavoriteConfig{
|
||||
sc: sc,
|
||||
tokenUser01: tokenUser01,
|
||||
tokenUser02: tokenUser02.Token,
|
||||
gwClientUser01: gwClientUser01,
|
||||
gwClientUser02: gwClientUser02,
|
||||
gwAdminClient: gwAdminClient,
|
||||
projects: projects,
|
||||
}
|
||||
|
||||
tt.f(ctx, t, tc)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetUserProjectFavorites(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
dir := t.TempDir()
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
sc := setup(ctx, t, dir, withGitea(true))
|
||||
defer sc.stop()
|
||||
|
||||
giteaToken, tokenUser01 := createLinkedAccount(ctx, t, sc.gitea, sc.config)
|
||||
gwClientUser01 := gwclient.NewClient(sc.config.Gateway.APIExposedURL, tokenUser01)
|
||||
|
||||
giteaAPIURL := fmt.Sprintf("http://%s:%s", sc.gitea.HTTPListenAddress, sc.gitea.HTTPPort)
|
||||
|
||||
giteaClient, err := gitea.NewClient(giteaAPIURL, gitea.SetToken(giteaToken))
|
||||
testutil.NilError(t, err)
|
||||
|
||||
allUserProjectFavorites := []*gwapitypes.UserProjectFavoriteResponse{}
|
||||
|
||||
_, project := createProject(ctx, t, giteaClient, gwClientUser01, withVisibility(gwapitypes.VisibilityPrivate))
|
||||
|
||||
userProjectFavorite, _, err := gwClientUser01.CreateUserProjectFavorite(ctx, &gwapitypes.CreateUserProjectFavoriteRequest{ProjectRef: project.ID})
|
||||
testutil.NilError(t, err)
|
||||
allUserProjectFavorites = append(allUserProjectFavorites, userProjectFavorite)
|
||||
|
||||
for i := 2; i < 10; i++ {
|
||||
project, _, err := gwClientUser01.CreateProject(ctx, &gwapitypes.CreateProjectRequest{
|
||||
Name: fmt.Sprintf("project0%d", i),
|
||||
ParentRef: path.Join("user", agolaUser01),
|
||||
RemoteSourceName: "gitea",
|
||||
RepoPath: path.Join(giteaUser01, "repo01"),
|
||||
Visibility: gwapitypes.VisibilityPublic,
|
||||
})
|
||||
testutil.NilError(t, err)
|
||||
|
||||
userProjectFavorite, _, err := gwClientUser01.CreateUserProjectFavorite(ctx, &gwapitypes.CreateUserProjectFavoriteRequest{ProjectRef: project.ID})
|
||||
testutil.NilError(t, err)
|
||||
|
||||
allUserProjectFavorites = append(allUserProjectFavorites, userProjectFavorite)
|
||||
}
|
||||
sort.Sort(userProjectFavoritesByID(allUserProjectFavorites))
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
limit int
|
||||
sortDirection gwapitypes.SortDirection
|
||||
expectedCallsNumber int
|
||||
}{
|
||||
{
|
||||
name: "get user project stars with limit = 0, no sortdirection",
|
||||
expectedCallsNumber: 1,
|
||||
},
|
||||
{
|
||||
name: "get user project stars with limit = 0",
|
||||
sortDirection: gwapitypes.SortDirectionAsc,
|
||||
expectedCallsNumber: 1,
|
||||
},
|
||||
{
|
||||
name: "get user project stars with limit less than results length",
|
||||
limit: 2,
|
||||
sortDirection: gwapitypes.SortDirectionAsc,
|
||||
expectedCallsNumber: 5,
|
||||
},
|
||||
{
|
||||
name: "get user project stars with limit greater than results length",
|
||||
limit: MaxLimit,
|
||||
sortDirection: gwapitypes.SortDirectionAsc,
|
||||
expectedCallsNumber: 1,
|
||||
},
|
||||
{
|
||||
name: "get user project stars with limit = 0, sortDirection desc",
|
||||
sortDirection: gwapitypes.SortDirectionDesc,
|
||||
expectedCallsNumber: 1,
|
||||
},
|
||||
{
|
||||
name: "get user project stars with limit less than results length, sortDirection desc",
|
||||
limit: 2,
|
||||
sortDirection: gwapitypes.SortDirectionDesc,
|
||||
expectedCallsNumber: 5,
|
||||
},
|
||||
{
|
||||
name: "get user project stars with limit greater than results length, sortDirection desc",
|
||||
limit: MaxLimit,
|
||||
sortDirection: gwapitypes.SortDirectionDesc,
|
||||
expectedCallsNumber: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var expectedUserProjectFavorites []*gwapitypes.UserProjectFavoriteResponse
|
||||
expectedUserProjectFavorites = append(expectedUserProjectFavorites, allUserProjectFavorites...)
|
||||
// default sortdirection is asc
|
||||
|
||||
// reverse if sortDirection is desc
|
||||
if tt.sortDirection == gwapitypes.SortDirectionDesc {
|
||||
slices.Reverse(expectedUserProjectFavorites)
|
||||
}
|
||||
|
||||
respAllUserProjectFavorites := []*gwapitypes.UserProjectFavoriteResponse{}
|
||||
sortDirection := tt.sortDirection
|
||||
callsNumber := 0
|
||||
var cursor string
|
||||
|
||||
for {
|
||||
respUserProjectFavorites, res, err := gwClientUser01.GetUserProjectFavorites(ctx, &gwclient.ListOptions{Cursor: cursor, Limit: tt.limit, SortDirection: sortDirection})
|
||||
testutil.NilError(t, err)
|
||||
|
||||
callsNumber++
|
||||
|
||||
respAllUserProjectFavorites = append(respAllUserProjectFavorites, respUserProjectFavorites...)
|
||||
|
||||
if res.Cursor == "" {
|
||||
break
|
||||
}
|
||||
cursor = res.Cursor
|
||||
sortDirection = ""
|
||||
}
|
||||
|
||||
assert.DeepEqual(t, expectedUserProjectFavorites, respAllUserProjectFavorites)
|
||||
assert.Assert(t, cmp.Equal(callsNumber, tt.expectedCallsNumber))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue