daf

package
v0.0.0-...-cbbd1a2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 5, 2022 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ArticleAdjustFavoritesCountDafT

type ArticleAdjustFavoritesCountDafT = func(
	ctx context.Context,
	tx pgx.Tx,
	slug string,
	delta int,
) (int, time.Time, error)

ArticleAdjustFavoritesCountDafT is the type of the stereotype instance for the DAF that increments the favorites count of an article.

var ArticleAdjustFavoritesCountDaf ArticleAdjustFavoritesCountDafT = func(
	ctx context.Context,
	tx pgx.Tx,
	slug string,
	delta int,
) (int, time.Time, error) {
	sql := `
	UPDATE articles 
	SET favorites_count = favorites_count + $2, updated_at = clock_timestamp() 
	WHERE slug = $1
	RETURNING favorites_count, updated_at
	`
	args := []any{
		slug,
		delta,
	}

	var favoritesCount int
	var updatedAt time.Time

	row := tx.QueryRow(ctx, sql, args...)
	if err := row.Scan(&favoritesCount, &updatedAt); err != nil {
		if err == pgx.ErrNoRows {
			err = dbpgx.DbErrRecordNotFound.Make(nil, bf.ErrMsgArticleSlugNotFound, slug)
		}
		return 0, time.Time{}, dbpgx.ClassifyError(err).Make(err, "")
	}

	return favoritesCount, updatedAt, nil
}

ArticleAdjustFavoritesCountDaf implements a stereotype instance of type ArticleAdjustFavoritesCountDafT.

type ArticleCreateDafT

type ArticleCreateDafT = func(ctx context.Context, tx pgx.Tx, article *model.Article) error

ArticleCreateDafT is the type of the stereotype instance for the DAF that creates an article.

var ArticleCreateDaf ArticleCreateDafT = func(
	ctx context.Context,
	tx pgx.Tx,
	article *model.Article,
) error {
	sql := `
	INSERT INTO articles (author_id, title, slug, description, body, favorites_count) 
	VALUES ($1, $2, $3, $4, $5, $6) 
	RETURNING id, created_at, updated_at
	`
	args := []any{
		article.AuthorId,
		article.Title,
		article.Slug,
		article.Description,
		article.Body,
		article.FavoritesCount,
	}

	row := tx.QueryRow(ctx, sql, args...)
	err := row.Scan(&article.Id, &article.CreatedAt, &article.UpdatedAt)
	if kind := dbpgx.ClassifyError(err); kind != nil {
		if kind == dbpgx.DbErrUniqueViolation {
			return kind.Make(err, bf.ErrMsgDuplicateArticleSlug, article.Slug)
		}
		return kind.Make(err, "")
	}
	return nil
}

ArticleCreateDaf implements a stereotype instance of type ArticleCreateDafT.

type ArticleDeleteDafT

type ArticleDeleteDafT = func(ctx context.Context, tx pgx.Tx, slug string) error

ArticleDeleteDafT is the type of the stereotype instance for the DAF that deletes an article.

var ArticleDeleteDaf ArticleDeleteDafT = func(
	ctx context.Context,
	tx pgx.Tx,
	slug string,
) error {
	sql := `
	DELETE FROM articles
	WHERE slug = $1
	`
	c, err := tx.Exec(ctx, sql, slug)
	if kind := dbpgx.ClassifyError(err); kind != nil {
		return kind.Make(err, "")
	}
	if c.RowsAffected() == 0 {
		return dbpgx.DbErrRecordNotFound.Make(nil, bf.ErrMsgArticleSlugNotFound, slug)
	}

	return nil
}

ArticleDeleteDaf implements a stereotype instance of type ArticleDeleteDafT.

type ArticleGetBySlugDafT

type ArticleGetBySlugDafT = func(ctx context.Context, tx pgx.Tx, currUserId uint, slug string) (model.ArticlePlus, error)

ArticleGetBySlugDafT is the type of the stereotype instance for the DAF that retrieves an article by slug.

var ArticleGetBySlugDaf ArticleGetBySlugDafT = func(
	ctx context.Context,
	tx pgx.Tx,
	currUserId uint,
	slug string,
) (model.ArticlePlus, error) {

	whereTuples := []types.Tuple2[string, any]{
		{"a.slug = $%d", slug},
	}
	where, whereArgs := whereClauseFromTuples(2, whereTuples)

	results, err := readArticles(ctx, tx, currUserId, where, nil, nil, whereArgs...)
	if err != nil {
		return model.ArticlePlus{}, err
	}
	if len(results) == 0 {
		return model.ArticlePlus{},
			dbpgx.DbErrRecordNotFound.Make(nil, bf.ErrMsgArticleSlugNotFound, slug)
	}
	if len(results) > 1 {
		return model.ArticlePlus{},
			dbpgx.DbErrUnexpectedMultipleRecords.Make(nil,
				"Found multiple articles with same slug '%v'", slug)
	}

	return results[0], nil
}

ArticleGetBySlugDaf implements a stereotype instance of type ArticleGetBySlugDafT.

type ArticleUpdateDafT

type ArticleUpdateDafT = func(ctx context.Context, tx pgx.Tx, article *model.Article) error

ArticleUpdateDafT is the type of the stereotype instance for the DAF that updates an article.

var ArticleUpdateDaf ArticleUpdateDafT = func(
	ctx context.Context,
	tx pgx.Tx,
	article *model.Article,
) error {
	sql := `
	UPDATE articles 
	SET title = $1, description = $2, body = $3, updated_at = clock_timestamp() 
	WHERE slug = $4 AND updated_at = $5
	RETURNING updated_at
	`
	args := []any{
		article.Title,
		article.Description,
		article.Body,
		article.Slug,
		article.UpdatedAt,
	}
	row := tx.QueryRow(ctx, sql, args...)
	if err := row.Scan(&article.UpdatedAt); err != nil {
		if err == pgx.ErrNoRows {
			err = dbpgx.DbErrRecordNotFound.Make(nil, bf.ErrMsgArticleSlugNotFound, article.Slug)
		}
		return dbpgx.ClassifyError(err).Make(err, "")
	}

	return nil
}

ArticleUpdateDaf implements a stereotype instance of type ArticleUpdateDafT.

type ArticlesFeedDafT

type ArticlesFeedDafT = func(ctx context.Context, tx pgx.Tx, currUserId uint, optLimit *int, optOffset *int) ([]model.ArticlePlus, error)

ArticlesFeedDafT is the type of the stereotype instance for the DAF that queries for all articles authored by other users followed by the current user, with optional limit and offset pagination parameters.

var ArticlesFeedDaf ArticlesFeedDafT = func(
	ctx context.Context,
	tx pgx.Tx,
	currUserId uint,
	optLimit *int,
	optOffset *int,
) ([]model.ArticlePlus, error) {

	whereTuples := []types.Tuple2[string, any]{
		{"fo.follower_id = $%d", currUserId},
	}
	where, whereArgs := whereClauseFromTuples(2, whereTuples)

	results, err := readArticles(ctx, tx, currUserId, where, optLimit, optOffset, whereArgs...)
	if err != nil {
		return nil, err
	}

	return results, nil
}

ArticlesFeedDaf implements a stereotype instance of type ArticlesFeedDafT.

type ArticlesListDafT

type ArticlesListDafT = func(ctx context.Context, tx pgx.Tx, currUserId uint, criteria rpc.ArticleCriteria) ([]model.ArticlePlus, error)

ArticlesListDafT is the type of the stereotype instance for the DAF that retrieve recent articles based on a set of query parameters.

var ArticlesListDaf ArticlesListDafT = func(
	ctx context.Context,
	tx pgx.Tx,
	currUserId uint,
	criteria rpc.ArticleCriteria,
) ([]model.ArticlePlus, error) {
	// See mainArticlePlusQuery
	var join string
	var joinArgs []any
	if v := criteria.FavoritedBy; v != nil {
		join = join + `
		LEFT JOIN favorites fa1 ON a.id = fa1.article_id -- at most one due to below
		LEFT JOIN users ufa1 ON ufa1.id = fa1.user_id -- AND ufa1.username = $2
		`

	}
	if v := criteria.Tag; v != nil {
		join = join + `
		LEFT JOIN article_tags at1 ON at1.article_id = a.id		
		LEFT JOIN tags t1 ON t1.id = at1.tag_id -- AND t1.name = $2
		`

	}

	var whereTuples []types.Tuple2[string, any]
	if v := criteria.FavoritedBy; v != nil {
		whereTuples = append(whereTuples, types.Tuple2[string, any]{"ufa1.username = $%d", *v})
	}
	if v := criteria.Tag; v != nil {
		whereTuples = append(whereTuples, types.Tuple2[string, any]{"t1.name = $%d", *v})
	}
	if v := criteria.Author; v != nil {
		whereTuples = append(whereTuples, types.Tuple2[string, any]{"ua.username = $%d", *v})
	}
	initialIndex := 2 + len(joinArgs)
	where, whereArgs := whereClauseFromTuples(initialIndex, whereTuples)

	additionalSql := join + where
	additionalArgs := append(joinArgs, whereArgs...)

	results, err := readArticles(ctx, tx, currUserId, additionalSql, criteria.Limit, criteria.Offset,
		additionalArgs...)
	if err != nil {
		return nil, err
	}

	return results, nil
}

ArticlesListDaf implements a stereotype instance of type ArticlesListDafT.

type CommentCreateDafT

type CommentCreateDafT = func(ctx context.Context, tx pgx.Tx, comment *model.Comment) error

CommentCreateDafT is the type of the stereotype instance for the DAF that creates a comment for an article.

var CommentCreateDaf CommentCreateDafT = func(
	ctx context.Context,
	tx pgx.Tx,
	comment *model.Comment,
) error {
	sql := `
	INSERT INTO comments (article_id, author_id, body) 
	VALUES ($1, $2, $3) 
	RETURNING id, created_at
	`
	args := []any{
		comment.ArticleId,
		comment.AuthorId,
		comment.Body,
	}

	row := tx.QueryRow(ctx, sql, args...)
	err := row.Scan(&comment.Id, &comment.CreatedAt)
	if kind := dbpgx.ClassifyError(err); kind != nil {
		return kind.Make(err, "")
	}
	return nil
}

CommentCreateDaf implements a stereotype instance of type CommentCreateDafT.

type CommentDeleteDafT

type CommentDeleteDafT = func(
	ctx context.Context,
	tx pgx.Tx,
	commentId uint,
	articleId uint,
	authorId uint,
) error

CommentDeleteDafT is the type of the stereotype instance for the DAF that deletes a comment.

var CommentDeleteDaf CommentDeleteDafT = func(
	ctx context.Context,
	tx pgx.Tx,
	commentId uint,
	articleId uint,
	authorId uint,
) error {
	sql := `
	DELETE FROM comments
	WHERE id = $1 AND article_id = $2 AND author_id = $3
	`
	args := []any{
		commentId,
		articleId,
		authorId,
	}

	c, err := tx.Exec(ctx, sql, args...)
	if kind := dbpgx.ClassifyError(err); kind != nil {
		return kind.Make(err, "")
	}
	if c.RowsAffected() == 0 {
		return dbpgx.DbErrRecordNotFound.Make(nil, bf.ErrMsgCommentNotFound)
	}

	return nil
}

CommentDeleteDaf implements a stereotype instance of type CommentDeleteDafT.

type CommentsGetBySlugDafT

type CommentsGetBySlugDafT = func(ctx context.Context, tx pgx.Tx, slug string) ([]model.Comment, error)

CommentsGetBySlugDafT is the type of the stereotype instance for the DAF that retrieves all comments for the article with a given slug.

var CommentsGetBySlugDaf CommentsGetBySlugDafT = func(
	ctx context.Context,
	tx pgx.Tx,
	slug string,
) ([]model.Comment, error) {
	sql := `
	SELECT c.* FROM comments c
	LEFT JOIN articles a ON c.article_id = a.id
	WHERE a.slug = $1
	`
	args := []any{slug}

	comments, err := dbpgx.ReadMany[model.Comment](ctx, tx, sql, -1, -1, args...)
	return comments, err
}

CommentsGetBySlugDaf implements a stereotype instance of type CommentGetBySlugDafT.

type FavoriteCreateDafT

type FavoriteCreateDafT = func(ctx context.Context, tx pgx.Tx, articleId uint, userId uint) error

FavoriteCreateDafT is the instance of the DAF stereotype that associates an article with a user that favors it.

var FavoriteCreateDaf FavoriteCreateDafT = func(
	ctx context.Context,
	tx pgx.Tx,
	articleId uint,
	userId uint,
) error {
	sql := `
	INSERT INTO favorites (article_id, user_id)
	VALUES ($1, $2)
	`
	args := []any{articleId, userId}
	_, err := tx.Exec(ctx, sql, args...)
	if kind := dbpgx.ClassifyError(err); kind != nil {
		if kind == dbpgx.DbErrUniqueViolation {
			return kind.Make(err, bf.ErrMsgArticleAlreadyFavorited, articleId)
		}
		return kind.Make(err, "")
	}
	return nil
}

FavoriteCreateDaf is the instance of the DAF stereotype that associates an article with a user that favors it.

type FavoriteDeleteDafT

type FavoriteDeleteDafT = func(ctx context.Context, tx pgx.Tx, articleId uint, userId uint) error

FavoriteDeleteDafT is the instance of the DAF stereotype that disaassociates an article from a user that favors it. Returns the number of rows affected, which can be 0 or 1.

var FavoriteDeleteDaf FavoriteDeleteDafT = func(
	ctx context.Context,
	tx pgx.Tx,
	articleId uint,
	userId uint,
) error {
	sql := `
	DELETE FROM favorites
	WHERE article_id = $1 AND user_id = $2
	`
	args := []any{articleId, userId}
	c, err := tx.Exec(ctx, sql, args...)
	if kind := dbpgx.ClassifyError(err); kind != nil {
		return kind.Make(err, "")
	}
	if c.RowsAffected() == 0 {
		return dbpgx.DbErrRecordNotFound.Make(nil, bf.ErrMsgArticleWasNotFavorited, articleId)
	}

	return nil
}

FavoriteDeleteDaf is the instance of the DAF stereotype that disaassociates an article from a user that favors it.

type FollowingCreateDafT

type FollowingCreateDafT = func(
	ctx context.Context,
	tx pgx.Tx,
	followerId uint,
	followeeId uint,
) (time.Time, error)

FollowingCreateDafT is the type of the stereotype instance for the DAF that associates a follower with a followee.

var FollowingCreateDaf FollowingCreateDafT = func(
	ctx context.Context,
	tx pgx.Tx,
	followerId uint,
	followeeId uint,
) (time.Time, error) {
	sql := `
	INSERT INTO followings (follower_id, followee_id)
	VALUES ($1, $2)
	RETURNING followed_on
	`
	args := []any{followerId, followeeId}

	var followedOn time.Time
	row := tx.QueryRow(ctx, sql, args...)
	err := row.Scan(&followedOn)
	if kind := dbpgx.ClassifyError(err); kind != nil {
		if kind == dbpgx.DbErrUniqueViolation {
			return time.Time{}, kind.Make(err, bf.ErrMsgUserAlreadyFollowed, followeeId)
		}
		return time.Time{}, kind.Make(err, "")
	}

	return followedOn, nil
}

FollowingCreateDaf is the instance of the DAF stereotype that associates a follower with a followee.

type FollowingDeleteDafT

type FollowingDeleteDafT = func(
	ctx context.Context,
	tx pgx.Tx,
	followerId uint,
	followeeId uint,
) error

FollowingDeleteDafT is the type of the stereotype instance for the DAF that disaassociates a follower from a followee.

var FollowingDeleteDaf FollowingDeleteDafT = func(
	ctx context.Context,
	tx pgx.Tx,
	followerId uint,
	followeeId uint,
) error {
	sql := `
	DELETE FROM followings
	WHERE follower_id = $1 AND followee_id = $2
	`
	args := []any{followerId, followeeId}
	c, err := tx.Exec(ctx, sql, args...)
	if kind := dbpgx.ClassifyError(err); kind != nil {
		return kind.Make(err, "")
	}
	if c.RowsAffected() == 0 {
		return dbpgx.DbErrRecordNotFound.Make(nil, bf.ErrMsgUserWasNotFollowed, followeeId)
	}

	return nil
}

FollowingDeleteDaf is the instance of the DAF stereotype that disaassociates a follower from a followee.

type FollowingGetDafT

type FollowingGetDafT = func(
	ctx context.Context,
	tx pgx.Tx,
	followerId uint,
	followeeId uint,
) (model.Following, error)

FollowingGetDafT is the type of the stereotype instance for the DAF that retrieves an association between a follower and a followee.

var FollowingGetDaf FollowingGetDafT = func(
	ctx context.Context,
	tx pgx.Tx,
	followerId uint,
	followeeId uint,
) (model.Following, error) {
	var zero model.Following

	sql := `
	SELECT * FROM followings 
	WHERE follower_id = $1 AND followee_id = $2
	`
	args := []any{
		followerId,
		followeeId,
	}

	rows, err := tx.Query(ctx, sql, args...)
	if kind := dbpgx.ClassifyError(err); kind != nil {
		return zero, kind.Make(err, "")
	}
	defer rows.Close()

	var following model.Following
	err = pgxscan.ScanOne(&following, rows)
	if kind := dbpgx.ClassifyError(err); kind != nil {
		if kind != dbpgx.DbErrRecordNotFound {
			return zero, kind.Make(err, "")
		}

	}

	return following, nil
}

FollowingGetDaf implements a stereotype instance of type FollowingGetDafT. Returns the association record if found or a zero model.Following otherwise.

type PwUser

type PwUser = db.Pw[model.User, RecCtxUser]

PwUser is a type alias

type RecCtxUser

type RecCtxUser = dbpgx.RecCtx[model.User]

RecCtxUser is a type alias

type TagAddToArticleDafT

type TagAddToArticleDafT = func(ctx context.Context, tx pgx.Tx, tag model.Tag, article model.Article) error

TagAddToArticleDafT is the type of the stereotype instance for the DAF that associates a tag with an article.

var TagAddToArticleDaf TagAddToArticleDafT = func(
	ctx context.Context,
	tx pgx.Tx,
	tag model.Tag,
	article model.Article,
) error {
	sql := `
	INSERT INTO article_tags (article_id, tag_id)
	VALUES ($1, $2)
	`
	args := []any{article.Id, tag.Id}
	_, err := tx.Exec(ctx, sql, args...)
	if kind := dbpgx.ClassifyError(err); kind != nil {
		if kind == dbpgx.DbErrUniqueViolation {
			return kind.Make(err, bf.ErrMsgTagOnArticleAlreadyExists, tag.Name, article.Slug)
		}
		return kind.Make(err, "")
	}
	return nil
}

TagAddToArticleDaf implements a stereotype instance of type TagAddToArticleDafT.

type TagCreateDafT

type TagCreateDafT = func(ctx context.Context, tx pgx.Tx, tag *model.Tag) error

TagCreateDafT is the type of the stereotype instance for the DAF that creates a new tag.

var TagCreateDaf TagCreateDafT = func(
	ctx context.Context,
	tx pgx.Tx,
	tag *model.Tag,
) error {
	sql := `
	INSERT INTO tags (name)
	VALUES ($1)
	RETURNING id
	`
	args := []any{strings.ToUpper(tag.Name)}
	row := tx.QueryRow(ctx, sql, args...)
	err := row.Scan(&tag.Id)
	if kind := dbpgx.ClassifyError(err); kind != nil {
		if kind == dbpgx.DbErrRecordNotFound {
			return dbpgx.DbErrUniqueViolation.Make(err, bf.ErrMsgTagNameAlreadyExists, tag.Name)
		}
		return kind.Make(err, "")
	}
	return nil
}

TagCreateDaf implements a stereotype instance of type TagCreateDafT.

type TagsAddNewDafT

type TagsAddNewDafT = func(ctx context.Context, tx pgx.Tx, names []string) error

TagsAddNewDafT is the type of the stereotype instance for the DAF that adds a list of tags, skipping those that already exist.

var TagsAddNewDaf TagsAddNewDafT = func(
	ctx context.Context,
	tx pgx.Tx,
	names []string,
) error {
	if len(names) == 0 {
		return nil
	}

	preSql := `
	INSERT INTO tags (name)
	SELECT x.name
	FROM (
		VALUES
			%v
	) x (name)
	WHERE NOT EXISTS (
		SELECT 1
		FROM tags t
		WHERE t.name = x.name
	)
	`
	var values []string
	for _, name := range names {
		values = append(values, fmt.Sprintf("('%v')", name))
	}
	valueString := strings.Join(values, ", ")
	sql := fmt.Sprintf(preSql, valueString)
	log.Debug("sql:", sql)

	_, err := tx.Exec(ctx, sql)
	if kind := dbpgx.ClassifyError(err); kind != nil {
		return kind.Make(err, "")
	}

	return nil
}

TagsAddNewDaf implements a stereotype instance of type TagsAddNewDafT.

type TagsAddToArticleDafT

type TagsAddToArticleDafT = func(ctx context.Context, tx pgx.Tx, names []string, article model.Article) error

TagsAddToArticleDafT is the type of the stereotype instance for the DAF that associates a list of tags with an article, skipping those that are already associated.

var TagsAddToArticleDaf TagsAddToArticleDafT = func(
	ctx context.Context,
	tx pgx.Tx,
	names []string,
	article model.Article,
) error {
	if len(names) == 0 {
		return nil
	}

	preSql := `
	INSERT INTO article_tags (article_id, tag_id)
	SELECT $1, t.id
	FROM tags t
	WHERE t.name IN (%v)
	AND NOT EXISTS (
			SELECT 1
			FROM article_tags at
			WHERE at.tag_id = t.id
	)
	`
	var values []string
	for _, name := range names {
		values = append(values, fmt.Sprintf("'%v'", name))
	}
	valueString := strings.Join(values, ", ")
	sql := fmt.Sprintf(preSql, valueString)
	log.Debug("sql:", sql)

	_, err := tx.Exec(ctx, sql, article.Id)
	if kind := dbpgx.ClassifyError(err); kind != nil {
		return kind.Make(err, "")
	}

	return nil
}

TagsAddToArticleDaf implements a stereotype instance of type TagsAddToArticleDafT.

type TagsGetAllDafT

type TagsGetAllDafT = func(ctx context.Context, tx pgx.Tx) ([]model.Tag, error)

TagsGetAllDafT is the type of the stereotype instance for the DAF that retrieves all tags.

var TagsGetAllDaf TagsGetAllDafT = func(ctx context.Context, tx pgx.Tx) ([]model.Tag, error) {
	mainSql := `
	SELECT * FROM tags
	`
	return dbpgx.ReadMany[model.Tag](ctx, tx, mainSql, -1, -1)
}

TagsGetAllDaf implements a stereotype instance of type TagsGetAllDafT.

type UserCreateDafT

type UserCreateDafT = func(ctx context.Context, user *model.User) (RecCtxUser, error)

UserCreateDafT is the type of the stereotype instance for the DAF that creates a user.

var UserCreateDaf UserCreateDafT = func(
	ctx context.Context,
	user *model.User,
) (RecCtxUser, error) {
	tx, err := dbpgx.GetCtxTx(ctx)
	if err != nil {
		return RecCtxUser{}, err
	}
	return UserCreateExplicitTxDaf(ctx, tx, user)
}

UserCreateDaf implements a stereotype instance of type UserCreateDafT.

type UserCreateExplicitTxDafT

type UserCreateExplicitTxDafT = func(ctx context.Context, tx pgx.Tx, user *model.User) (RecCtxUser, error)

UserCreateExplicitTxDafT is the type of the stereotype instance for the DAF that creates a user taking an explicit pgx.Tx.

var UserCreateExplicitTxDaf UserCreateExplicitTxDafT = func(
	ctx context.Context,
	tx pgx.Tx,
	user *model.User,
) (RecCtxUser, error) {
	sql := `
	INSERT INTO users (username, email, password_hash, password_salt, bio, image)
	VALUES ($1, $2, $3, $4, $5, $6)
	RETURNING id, created_at, updated_at
	`
	user.Email = strings.ToLower(user.Email)
	args := []any{
		user.Username,
		user.Email,
		user.PasswordHash,
		user.PasswordSalt,
		user.Bio,
		user.ImageLink,
	}
	row := tx.QueryRow(ctx, sql, args...)
	var recCtx RecCtxUser
	err := row.Scan(&user.Id, &recCtx.CreatedAt, &recCtx.UpdatedAt)
	if kind := dbpgx.ClassifyError(err); kind != nil {
		if kind == dbpgx.DbErrUniqueViolation {
			return RecCtxUser{}, kind.Make(
				err,
				bf.ErrMsgUsernameOrEmailDuplicate,
				user.Username,
				user.Email,
			)
		}
		return RecCtxUser{}, kind.Make(err, "")
	}

	return recCtx, nil
}

UserCreateExplicitTxDaf implements a stereotype instance of type UserCreateDafT.

type UserGetByEmailDafT

type UserGetByEmailDafT = func(ctx context.Context, email string) (model.User, RecCtxUser, error)

UserGetByEmailDafT is the type of the stereotype instance for the DAF that retrieves a user by email address.

var UserGetByEmailDaf UserGetByEmailDafT = func(
	ctx context.Context,
	email string,
) (model.User, RecCtxUser, error) {
	tx, err := dbpgx.GetCtxTx(ctx)
	if err != nil {
		return model.User{}, RecCtxUser{}, err
	}
	pwUser := PwUser{}
	err = dbpgx.ReadSingle(ctx, tx, "users", "email", strings.ToLower(email), &pwUser)
	if kind := dbpgx.ClassifyError(err); kind != nil {
		if kind == dbpgx.DbErrRecordNotFound {
			return model.User{}, RecCtxUser{},
				kind.Decorate(util.SafeCast[errx.Errx](err), bf.ErrMsgUserEmailNotFound, email)
		}
		return model.User{}, RecCtxUser{}, err
	}
	return pwUser.Entity, pwUser.RecCtx, nil
}

UserGetByEmailDaf implements a stereotype instance of type UserGetByEmailDafT.

type UserGetByNameDafT

type UserGetByNameDafT = func(ctx context.Context, userName string) (model.User, RecCtxUser, error)

UserGetByNameDafT is the type of the stereotype instance for the DAF that retrieves a user by username.

var UserGetByNameDaf UserGetByNameDafT = func(
	ctx context.Context,
	username string,
) (model.User, RecCtxUser, error) {
	tx, err := dbpgx.GetCtxTx(ctx)
	if err != nil {
		return model.User{}, RecCtxUser{}, err
	}
	return UserGetByNameExplicitTxDaf(ctx, tx, username)
}

UserGetByNameDaf implements a stereotype instance of type UserGetByNameDafT.

type UserGetByNameExplicitTxDafT

type UserGetByNameExplicitTxDafT = func(
	ctx context.Context,
	tx pgx.Tx,
	username string,
) (model.User, RecCtxUser, error)

UserGetByNameExplicitTxDafT is the type of the stereotype instance for the DAF that retrieves a user by username taking an explicit pgx.Tx.

var UserGetByNameExplicitTxDaf UserGetByNameExplicitTxDafT = func(
	ctx context.Context,
	tx pgx.Tx,
	username string,
) (model.User, RecCtxUser, error) {
	pwUser := PwUser{}
	err := dbpgx.ReadSingle(ctx, tx, "users", "username", username, &pwUser)
	if kind := dbpgx.ClassifyError(err); kind != nil {
		if kind == dbpgx.DbErrRecordNotFound {
			errX := util.SafeCast[errx.Errx](err)
			return model.User{}, RecCtxUser{}, errX.Customize(bf.ErrMsgUsernameNotFound, username)
		}
		return model.User{}, RecCtxUser{}, err
	}
	return pwUser.Entity, pwUser.RecCtx, nil
}

UserGetByNameExplicitTxDaf implements a stereotype instance of type UserGetByNameDafT with explicit passing of a pgx.Tx.

type UserUpdateDafT

type UserUpdateDafT = func(ctx context.Context, user model.User, recCtx RecCtxUser) (RecCtxUser, error)

UserUpdateDafT is the type of the stereotype instance for the DAF that updates a user.

var UserUpdateDaf UserUpdateDafT = func(
	ctx context.Context,
	user model.User,
	recCtx RecCtxUser,
) (RecCtxUser, error) {
	tx, err := dbpgx.GetCtxTx(ctx)
	if err != nil {
		return RecCtxUser{}, errx.ErrxOf(err)
	}
	sql := `
	UPDATE users 
	SET username = $1, email = $2, bio = $3, image = $4, password_hash = $5, password_salt = $6, 
		updated_at = clock_timestamp()
	WHERE id = $7 AND updated_at = $8
	RETURNING updated_at
	`
	user.Email = strings.ToLower(user.Email)
	args := []interface{}{
		user.Username,
		user.Email,
		user.Bio,
		user.ImageLink,
		user.PasswordHash,
		user.PasswordSalt,
		user.Id,
		recCtx.UpdatedAt,
	}
	log.Debug("UserUpdateDaf sql: ", sql)
	log.Debug("UserUpdateDaf args: ", args)

	newRecCtx := recCtx
	row := tx.QueryRow(ctx, sql, args...)
	err = row.Scan(&newRecCtx.UpdatedAt)
	if kind := dbpgx.ClassifyError(err); kind != nil {
		if kind == dbpgx.DbErrUniqueViolation {
			return RecCtxUser{}, kind.Make(
				err,
				bf.ErrMsgUsernameOrEmailDuplicate,
				user.Username,
				user.Email,
			)
		}
		return RecCtxUser{}, kind.Make(err, "")
	}

	return newRecCtx, nil
}

UserUpdateDaf implements a stereotype instance of type UserUpdateDafT.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL