package postgres import ( "context" "errors" "github.com/jackc/pgx/v4" "go.uber.org/zap" "serverctl/pkg/application/applications" "serverctl/pkg/db" ) type ApplicationRepository struct { db *db.Client logger *zap.Logger } var _ applications.Repository = ApplicationRepository{} func NewApplicationRepository(logger *zap.Logger, db *db.Client) applications.Repository { return &ApplicationRepository{logger: logger, db: db} } func (a ApplicationRepository) CreateApplication(ctx context.Context, name string, userId int, projectId int) (int, error) { conn := a.db.GetConn(ctx) defer conn.Release() var applicationId int err := conn.BeginTxFunc(ctx, pgx.TxOptions{}, func(tx pgx.Tx) error { var exists bool err := tx.QueryRow( ctx, "select exists(select 1 from sctl_project_member where project_id = $1 and member_id = $2 and role = 'admin')", projectId, userId, ).Scan(&exists) if err != nil { a.logger.Info("cannot query project member status in database", zap.Int("userId", userId), zap.Int("projectId", projectId), zap.String("error", err.Error())) return err } if !exists { a.logger.Info("cannot create application as user isn't admin for project, or project doesn't exist", zap.Int("userId", userId), zap.Int("projectId", projectId)) return errors.New("user isn't admin or admin of project") } err = tx.QueryRow(ctx, "insert into sctl_application(name, project_id) values($1, $2) returning id", name, projectId).Scan(&applicationId) if err != nil { a.logger.Info("could not create application", zap.String("error", err.Error())) return err } return nil }) if err != nil { return -1, err } return applicationId, nil }