gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

user.go (5265B)


      1 // GoToSocial
      2 // Copyright (C) GoToSocial Authors admin@gotosocial.org
      3 // SPDX-License-Identifier: AGPL-3.0-or-later
      4 //
      5 // This program is free software: you can redistribute it and/or modify
      6 // it under the terms of the GNU Affero General Public License as published by
      7 // the Free Software Foundation, either version 3 of the License, or
      8 // (at your option) any later version.
      9 //
     10 // This program is distributed in the hope that it will be useful,
     11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 // GNU Affero General Public License for more details.
     14 //
     15 // You should have received a copy of the GNU Affero General Public License
     16 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
     17 
     18 package bundb
     19 
     20 import (
     21 	"context"
     22 	"errors"
     23 	"time"
     24 
     25 	"github.com/superseriousbusiness/gotosocial/internal/db"
     26 	"github.com/superseriousbusiness/gotosocial/internal/gtscontext"
     27 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
     28 	"github.com/superseriousbusiness/gotosocial/internal/state"
     29 	"github.com/uptrace/bun"
     30 )
     31 
     32 type userDB struct {
     33 	conn  *DBConn
     34 	state *state.State
     35 }
     36 
     37 func (u *userDB) GetUserByID(ctx context.Context, id string) (*gtsmodel.User, db.Error) {
     38 	return u.state.Caches.GTS.User().Load("ID", func() (*gtsmodel.User, error) {
     39 		var user gtsmodel.User
     40 
     41 		q := u.conn.
     42 			NewSelect().
     43 			Model(&user).
     44 			Relation("Account").
     45 			Where("? = ?", bun.Ident("user.id"), id)
     46 
     47 		if err := q.Scan(ctx); err != nil {
     48 			return nil, u.conn.ProcessError(err)
     49 		}
     50 
     51 		return &user, nil
     52 	}, id)
     53 }
     54 
     55 func (u *userDB) GetUserByAccountID(ctx context.Context, accountID string) (*gtsmodel.User, db.Error) {
     56 	return u.state.Caches.GTS.User().Load("AccountID", func() (*gtsmodel.User, error) {
     57 		var user gtsmodel.User
     58 
     59 		q := u.conn.
     60 			NewSelect().
     61 			Model(&user).
     62 			Relation("Account").
     63 			Where("? = ?", bun.Ident("user.account_id"), accountID)
     64 
     65 		if err := q.Scan(ctx); err != nil {
     66 			return nil, u.conn.ProcessError(err)
     67 		}
     68 
     69 		return &user, nil
     70 	}, accountID)
     71 }
     72 
     73 func (u *userDB) GetUserByEmailAddress(ctx context.Context, emailAddress string) (*gtsmodel.User, db.Error) {
     74 	return u.state.Caches.GTS.User().Load("Email", func() (*gtsmodel.User, error) {
     75 		var user gtsmodel.User
     76 
     77 		q := u.conn.
     78 			NewSelect().
     79 			Model(&user).
     80 			Relation("Account").
     81 			Where("? = ?", bun.Ident("user.email"), emailAddress)
     82 
     83 		if err := q.Scan(ctx); err != nil {
     84 			return nil, u.conn.ProcessError(err)
     85 		}
     86 
     87 		return &user, nil
     88 	}, emailAddress)
     89 }
     90 
     91 func (u *userDB) GetUserByExternalID(ctx context.Context, id string) (*gtsmodel.User, db.Error) {
     92 	return u.state.Caches.GTS.User().Load("ExternalID", func() (*gtsmodel.User, error) {
     93 		var user gtsmodel.User
     94 
     95 		q := u.conn.
     96 			NewSelect().
     97 			Model(&user).
     98 			Relation("Account").
     99 			Where("? = ?", bun.Ident("user.external_id"), id)
    100 
    101 		if err := q.Scan(ctx); err != nil {
    102 			return nil, u.conn.ProcessError(err)
    103 		}
    104 
    105 		return &user, nil
    106 	}, id)
    107 }
    108 
    109 func (u *userDB) GetUserByConfirmationToken(ctx context.Context, confirmationToken string) (*gtsmodel.User, db.Error) {
    110 	return u.state.Caches.GTS.User().Load("ConfirmationToken", func() (*gtsmodel.User, error) {
    111 		var user gtsmodel.User
    112 
    113 		q := u.conn.
    114 			NewSelect().
    115 			Model(&user).
    116 			Relation("Account").
    117 			Where("? = ?", bun.Ident("user.confirmation_token"), confirmationToken)
    118 
    119 		if err := q.Scan(ctx); err != nil {
    120 			return nil, u.conn.ProcessError(err)
    121 		}
    122 
    123 		return &user, nil
    124 	}, confirmationToken)
    125 }
    126 
    127 func (u *userDB) GetAllUsers(ctx context.Context) ([]*gtsmodel.User, db.Error) {
    128 	var users []*gtsmodel.User
    129 	q := u.conn.
    130 		NewSelect().
    131 		Model(&users).
    132 		Relation("Account")
    133 
    134 	if err := q.Scan(ctx); err != nil {
    135 		return nil, u.conn.ProcessError(err)
    136 	}
    137 
    138 	return users, nil
    139 }
    140 
    141 func (u *userDB) PutUser(ctx context.Context, user *gtsmodel.User) db.Error {
    142 	return u.state.Caches.GTS.User().Store(user, func() error {
    143 		_, err := u.conn.
    144 			NewInsert().
    145 			Model(user).
    146 			Exec(ctx)
    147 		return u.conn.ProcessError(err)
    148 	})
    149 }
    150 
    151 func (u *userDB) UpdateUser(ctx context.Context, user *gtsmodel.User, columns ...string) db.Error {
    152 	// Update the user's last-updated
    153 	user.UpdatedAt = time.Now()
    154 
    155 	if len(columns) > 0 {
    156 		// If we're updating by column, ensure "updated_at" is included
    157 		columns = append(columns, "updated_at")
    158 	}
    159 
    160 	return u.state.Caches.GTS.User().Store(user, func() error {
    161 		_, err := u.conn.
    162 			NewUpdate().
    163 			Model(user).
    164 			Where("? = ?", bun.Ident("user.id"), user.ID).
    165 			Column(columns...).
    166 			Exec(ctx)
    167 		return u.conn.ProcessError(err)
    168 	})
    169 }
    170 
    171 func (u *userDB) DeleteUserByID(ctx context.Context, userID string) db.Error {
    172 	defer u.state.Caches.GTS.User().Invalidate("ID", userID)
    173 
    174 	// Load user into cache before attempting a delete,
    175 	// as we need it cached in order to trigger the invalidate
    176 	// callback. This in turn invalidates others.
    177 	_, err := u.GetUserByID(gtscontext.SetBarebones(ctx), userID)
    178 	if err != nil {
    179 		if errors.Is(err, db.ErrNoEntries) {
    180 			// not an issue.
    181 			err = nil
    182 		}
    183 		return err
    184 	}
    185 
    186 	// Finally delete user from DB.
    187 	_, err = u.conn.NewDelete().
    188 		TableExpr("? AS ?", bun.Ident("users"), bun.Ident("user")).
    189 		Where("? = ?", bun.Ident("user.id"), userID).
    190 		Exec(ctx)
    191 	return u.conn.ProcessError(err)
    192 }