Migrate from ent to sqlc

This commit is contained in:
Tony Grosinger 2024-07-11 21:09:15 -07:00
parent d08f5f55aa
commit bd54486fb3
60 changed files with 785 additions and 7383 deletions

4
.gitignore vendored
View File

@ -1,2 +1,2 @@
.idea
dbs
data.db*

View File

@ -1,18 +1,3 @@
# Install Ent code-generation module
.PHONY: ent-install
ent-install:
go get -d entgo.io/ent/cmd/ent
# Generate Ent code
.PHONY: ent-gen
ent-gen:
go generate ./ent
# Create a new Ent entity
.PHONY: ent-new
ent-new:
go run entgo.io/ent/cmd/ent new $(name)
# Run the application
.PHONY: run
run:
@ -24,6 +9,11 @@ run:
test:
go test -count=1 -p 1 ./...
.PHONY: sqlc
sqlc:
rm -f pkg/models/sqlc/*
sqlc generate
# Check for direct dependency updates
.PHONY: check-updates
check-updates:

View File

@ -31,9 +31,7 @@
* [Database](#database)
* [Auto-migrations](#auto-migrations)
* [Separate test database](#separate-test-database)
* [ORM](#orm)
* [Entity types](#entity-types)
* [New entity type](#new-entity-type)
* [SQLC](#sqlc)
* [Sessions](#sessions)
* [Encryption](#encryption)
* [Authentication](#authentication)
@ -173,7 +171,6 @@ The container is located at `pkg/services/container.go` and is meant to house al
- Configuration
- Cache
- Database
- ORM
- Web
- Validator
- Authentication
@ -238,13 +235,13 @@ func TestMain(m *testing.M) {
## Database
The database currently used is [SQLite](https://sqlite.org/) but you are free to use whatever you prefer. If you plan to continue using [Ent](https://entgo.io/), the incredible ORM, you can check their supported databases [here](https://entgo.io/docs/dialects). The database driver is provided by [go-sqlite3](https://github.com/mattn/go-sqlite3). A reference to the database is included in the `Container` if direct access is required.
The database currently used is [SQLite](https://sqlite.org/) but you are free to use whatever you prefer. The database driver is provided by [go-sqlite3](https://github.com/mattn/go-sqlite3). A reference to the database is included in the `Container` if direct access is required.
Database configuration can be found and managed within the `config` package.
### Auto-migrations
[Ent](https://entgo.io/) provides automatic migrations which are executed on the database whenever the `Container` is created, which means they will run when the application starts.
[Golang Migrate](github.com/golang-migrate/migrate) provides automati migrat-ns on the database whenever the application starts. Migrations are written in the `db/migrations` directory, which must be present at runtime in the container.
### Separate test database
@ -254,41 +251,12 @@ When a `Container` is created, if the [environment](#environments) is set to `co
When this project was using Postgres, it would automatically drop and recreate the test database. Since the current default is in-memory, that is no longer needed. If you decide to use a test database not in-memory, you can alter the `Container` initialization code to do this for you.
## ORM
## SQLC
As previously mentioned, [Ent](https://entgo.io/) is the supplied ORM. It can swapped out, but I highly recommend it. I don't think there is anything comparable for Go, at the current time. If you're not familiar with Ent, take a look through their top-notch [documentation](https://entgo.io/docs/getting-started).
Database interactions are handled using [sqlc](https://sqlc.dev) by writing raw SQL queries in the `database/queries` directory and then generating the necessary boilerplate code with `make sqlc`. This creates functions available on the `DBClient.C` object for each written query.
An Ent client is included in the `Container` to provide easy access to the ORM throughout the application.
If you want to group business logic for the database into functions beyond what can be performed in a single SQL query, you can create a sub-client, such as the example`DBUserClient` and attach methods which have access to the database.
Ent relies on code-generation for the entities you create to provide robust, type-safe data operations. Everything within the `ent` package in this repository is generated code for the two entity types listed below with the exception of the schema declaration.
### Entity types
The two included entity types are:
- User
- PasswordToken
### New entity type
While you should refer to their [documentation](https://entgo.io/docs/getting-started) for detailed usage, it's helpful to understand how to create an entity type and generate code. To make this easier, the `Makefile` contains some helpers.
1. Ensure all Ent code is downloaded by executing `make ent-install`.
2. Create the new entity type by executing `make ent-new name=User` where `User` is the name of the entity type. This will generate a file like you can see in `ent/schema/user.go` though the `Fields()` and `Edges()` will be left empty.
3. Populate the `Fields()` and optionally the `Edges()` (which are the relationships to other entity types).
4. When done, generate all code by executing `make ent-gen`.
The generated code is extremely flexible and impressive. An example to highlight this is one used within this application:
```go
entity, err := c.ORM.PasswordToken.
Query().
Where(passwordtoken.ID(tokenID)).
Where(passwordtoken.HasUserWith(user.ID(userID))).
Where(passwordtoken.CreatedAtGTE(expiration)).
Only(ctx.Request().Context())
```
This executes a database query to return the _password token_ entity with a given ID that belong to a user with a given ID and has a _created at_ timestamp field that is greater than or equal to a given time.
## Sessions
@ -386,13 +354,13 @@ A `Handler` is a simple type that handles one or more of your routes and allows
The provided patterns are not required, but were designed to make development as easy as possible.
For this example, we'll create a new handler which includes a GET and POST route and uses the ORM. Start by creating a file at `pkg/handlers/example.go`.
For this example, we'll create a new handler which includes a GET and POST route and uses the database. Start by creating a file at `pkg/handlers/example.go`.
1) Define the handler type:
```go
type Example struct {
orm *ent.Client
db *services.DBClient
*services.TemplateRenderer
}
```
@ -410,7 +378,7 @@ func init() {
```go
func (e *Example) Init(c *services.Container) error {
e.TemplateRenderer = c.TemplateRenderer
e.orm = c.ORM
e.db = c.DB
return nil
}
```
@ -1054,7 +1022,7 @@ Tasks can be created and queued with various chained options:
err := c.Tasks.
New(task).
Wait(30 * time.Second). // Wait 30 seconds before passing the task to the subscriber
At(time.Date(...)). // Wait until a given date before passing the task to the subscriber
At(time.Date(...)). // Wait until a given date before passing the task to the subscriber
Tx(tx). // Include the queueing of this task in a database transaction
Save()
```
@ -1156,7 +1124,7 @@ The provided implementation uses the relatively new [log/slog](https://go.dev/bl
### Context
The simple `pkg/log` package provides the ability to set and get a logger from the Echo context. This is especially useful when you use the provided logger middleware (see below). If you intend to use a different logger, modify these methods to receive and return the logger of your choice.
The simple `pkg/log` package provides the ability to set and get a logger from the Echo context. This is especially useful when you use the provided logger middleware (see below). If you intend to use a different logger, modify these methods to receive and return the logger of your choice.
### Usage
@ -1205,7 +1173,7 @@ Thank you to all of the following amazing projects for making this possible.
- [alpinejs](https://github.com/alpinejs/alpine)
- [bulma](https://github.com/jgthms/bulma)
- [echo](https://github.com/labstack/echo)
- [ent](https://github.com/ent/ent)
- [golang-migrate](https://github.com/golang-migrate/migrate)
- [go](https://go.dev/)
- [go-sqlite3](https://github.com/mattn/go-sqlite3)
- [goqite](https://github.com/maragudk/goqite)
@ -1218,4 +1186,4 @@ Thank you to all of the following amazing projects for making this possible.
- [sqlite](https://sqlite.org/)
- [testify](https://github.com/stretchr/testify)
- [validator](https://github.com/go-playground/validator)
- [viper](https://github.com/spf13/viper)
- [viper](https://github.com/spf13/viper)

View File

@ -26,10 +26,9 @@ cache:
staticFile: "4380h"
page: "24h"
database:
driver: "sqlite3"
connection: "dbs/main.db?_journal=WAL&_timeout=5000&_fk=true"
testConnection: ":memory:?_journal=WAL&_timeout=5000&_fk=true"
storage:
databaseFile: "data.db"
migrationsDir: db/migrations
tasks:
pollInterval: "1s"

View File

@ -2,6 +2,7 @@ package config
import (
"os"
"path/filepath"
"strings"
"time"
@ -53,12 +54,12 @@ func SwitchEnvironment(env environment) {
type (
// Config stores complete configuration
Config struct {
HTTP HTTPConfig
App AppConfig
Cache CacheConfig
Database DatabaseConfig
Tasks TasksConfig
Mail MailConfig
HTTP HTTPConfig
App AppConfig
Cache CacheConfig
Storage StorageConfig
Tasks TasksConfig
Mail MailConfig
}
// HTTPConfig stores HTTP configuration
@ -97,11 +98,15 @@ type (
}
}
// DatabaseConfig stores the database configuration
DatabaseConfig struct {
Driver string
Connection string
TestConnection string
// StorageConfig stores the storage configuration
StorageConfig struct {
// DatabaseFile is the path used to find the database file.
// It can be an absolute path, or a path relative to the config file location.
DatabaseFile string
// MigrationsDir is the path used to find the migration files.
// It can be an absolute path, or a path relative to the config file location.
MigrationsDir string
}
// TasksConfig stores the tasks configuration
@ -130,8 +135,8 @@ func GetConfig() (Config, error) {
viper.SetConfigType("yaml")
viper.AddConfigPath(".")
viper.AddConfigPath("config")
viper.AddConfigPath("../config")
viper.AddConfigPath("../../config")
viper.AddConfigPath("../")
viper.AddConfigPath("../../")
// Load env variables
viper.SetEnvPrefix("pagoda")
@ -146,5 +151,14 @@ func GetConfig() (Config, error) {
return c, err
}
usedConfigFilePath := viper.GetViper().ConfigFileUsed()
configFileDir := filepath.Dir(usedConfigFilePath)
if !filepath.IsAbs(c.Storage.DatabaseFile) {
c.Storage.DatabaseFile = filepath.Join(configFileDir, c.Storage.DatabaseFile)
}
if !filepath.IsAbs(c.Storage.MigrationsDir) {
c.Storage.MigrationsDir = filepath.Join(configFileDir, c.Storage.MigrationsDir)
}
return c, nil
}

View File

@ -0,0 +1,23 @@
CREATE TABLE password_tokens (
id integer NOT NULL PRIMARY KEY AUTOINCREMENT,
hash text NOT NULL,
created_at text NOT NULL DEFAULT CURRENT_TIMESTAMP,
password_token_user integer NOT NULL,
CONSTRAINT `password_tokens_users_user`
FOREIGN KEY (`password_token_user`)
REFERENCES `users` (`id`)
ON DELETE NO ACTION
) STRICT;
CREATE TABLE users (
id integer NOT NULL PRIMARY KEY AUTOINCREMENT,
name text NOT NULL,
email text NOT NULL,
password text NOT NULL,
verified integer NOT NULL DEFAULT 0,
created_at text NOT NULL DEFAULT CURRENT_TIMESTAMP
) STRICT;
CREATE UNIQUE INDEX `users_email_key` ON `users` (`email`);

View File

@ -0,0 +1,30 @@
-- name: GetAllPasswordTokensForUser :many
-- GetAllPasswordTokensForUser retrieves all password tokens without checking expiration.
SELECT * FROM password_tokens
WHERE password_token_user = ?;
-- name: GetValidPasswordToken :one
-- GetValidPasswordToken returns only valid password tokens for the provided
-- user, and only if the created_at time is greater than the provided time.
SELECT * FROM password_tokens
WHERE
id = ?
AND password_token_user = ?
AND datetime(created_at) > datetime(?)
LIMIT 1;
-- name: CreatePasswordToken :one
INSERT INTO password_tokens (
hash, password_token_user
) VALUES (
?, ?
) RETURNING *;
-- name: UpdatePasswordTokenCreatedAt :exec
UPDATE password_tokens
SET created_at = ?
WHERE id = ?;
-- name: DeletePasswordTokens :exec
DELETE FROM password_tokens
WHERE password_token_user = ?;

27
db/queries/users.sql Normal file
View File

@ -0,0 +1,27 @@
-- name: GetUserByEmail :one
SELECT * FROM users
WHERE email = lower(?)
LIMIT 1;
-- name: GetUserByID :one
SELECT * FROM users
WHERE id = ?
LIMIT 1;
-- name: CreateUser :one
INSERT INTO users (
name, email, password
) VALUES (
?, ?, ?
) RETURNING *;
-- name: UpdateUserPassword :exec
UPDATE users
SET password = ?
WHERE id = ?;
-- name: UpdateUserSetVerified :exec
UPDATE users
SET verified = 1
WHERE email = ?;

View File

@ -1,517 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"errors"
"fmt"
"log"
"reflect"
"entgo.io/ent"
"entgo.io/ent/dialect"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"git.grosinger.net/tgrosinger/saasitone/ent/migrate"
"git.grosinger.net/tgrosinger/saasitone/ent/passwordtoken"
"git.grosinger.net/tgrosinger/saasitone/ent/user"
)
// Client is the client that holds all ent builders.
type Client struct {
config
// Schema is the client for creating, migrating and dropping schema.
Schema *migrate.Schema
// PasswordToken is the client for interacting with the PasswordToken builders.
PasswordToken *PasswordTokenClient
// User is the client for interacting with the User builders.
User *UserClient
}
// NewClient creates a new client configured with the given options.
func NewClient(opts ...Option) *Client {
client := &Client{config: newConfig(opts...)}
client.init()
return client
}
func (c *Client) init() {
c.Schema = migrate.NewSchema(c.driver)
c.PasswordToken = NewPasswordTokenClient(c.config)
c.User = NewUserClient(c.config)
}
type (
// config is the configuration for the client and its builder.
config struct {
// driver used for executing database requests.
driver dialect.Driver
// debug enable a debug logging.
debug bool
// log used for logging on debug mode.
log func(...any)
// hooks to execute on mutations.
hooks *hooks
// interceptors to execute on queries.
inters *inters
}
// Option function to configure the client.
Option func(*config)
)
// newConfig creates a new config for the client.
func newConfig(opts ...Option) config {
cfg := config{log: log.Println, hooks: &hooks{}, inters: &inters{}}
cfg.options(opts...)
return cfg
}
// options applies the options on the config object.
func (c *config) options(opts ...Option) {
for _, opt := range opts {
opt(c)
}
if c.debug {
c.driver = dialect.Debug(c.driver, c.log)
}
}
// Debug enables debug logging on the ent.Driver.
func Debug() Option {
return func(c *config) {
c.debug = true
}
}
// Log sets the logging function for debug mode.
func Log(fn func(...any)) Option {
return func(c *config) {
c.log = fn
}
}
// Driver configures the client driver.
func Driver(driver dialect.Driver) Option {
return func(c *config) {
c.driver = driver
}
}
// Open opens a database/sql.DB specified by the driver name and
// the data source name, and returns a new client attached to it.
// Optional parameters can be added for configuring the client.
func Open(driverName, dataSourceName string, options ...Option) (*Client, error) {
switch driverName {
case dialect.MySQL, dialect.Postgres, dialect.SQLite:
drv, err := sql.Open(driverName, dataSourceName)
if err != nil {
return nil, err
}
return NewClient(append(options, Driver(drv))...), nil
default:
return nil, fmt.Errorf("unsupported driver: %q", driverName)
}
}
// ErrTxStarted is returned when trying to start a new transaction from a transactional client.
var ErrTxStarted = errors.New("ent: cannot start a transaction within a transaction")
// Tx returns a new transactional client. The provided context
// is used until the transaction is committed or rolled back.
func (c *Client) Tx(ctx context.Context) (*Tx, error) {
if _, ok := c.driver.(*txDriver); ok {
return nil, ErrTxStarted
}
tx, err := newTx(ctx, c.driver)
if err != nil {
return nil, fmt.Errorf("ent: starting a transaction: %w", err)
}
cfg := c.config
cfg.driver = tx
return &Tx{
ctx: ctx,
config: cfg,
PasswordToken: NewPasswordTokenClient(cfg),
User: NewUserClient(cfg),
}, nil
}
// BeginTx returns a transactional client with specified options.
func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) {
if _, ok := c.driver.(*txDriver); ok {
return nil, errors.New("ent: cannot start a transaction within a transaction")
}
tx, err := c.driver.(interface {
BeginTx(context.Context, *sql.TxOptions) (dialect.Tx, error)
}).BeginTx(ctx, opts)
if err != nil {
return nil, fmt.Errorf("ent: starting a transaction: %w", err)
}
cfg := c.config
cfg.driver = &txDriver{tx: tx, drv: c.driver}
return &Tx{
ctx: ctx,
config: cfg,
PasswordToken: NewPasswordTokenClient(cfg),
User: NewUserClient(cfg),
}, nil
}
// Debug returns a new debug-client. It's used to get verbose logging on specific operations.
//
// client.Debug().
// PasswordToken.
// Query().
// Count(ctx)
func (c *Client) Debug() *Client {
if c.debug {
return c
}
cfg := c.config
cfg.driver = dialect.Debug(c.driver, c.log)
client := &Client{config: cfg}
client.init()
return client
}
// Close closes the database connection and prevents new queries from starting.
func (c *Client) Close() error {
return c.driver.Close()
}
// Use adds the mutation hooks to all the entity clients.
// In order to add hooks to a specific client, call: `client.Node.Use(...)`.
func (c *Client) Use(hooks ...Hook) {
c.PasswordToken.Use(hooks...)
c.User.Use(hooks...)
}
// Intercept adds the query interceptors to all the entity clients.
// In order to add interceptors to a specific client, call: `client.Node.Intercept(...)`.
func (c *Client) Intercept(interceptors ...Interceptor) {
c.PasswordToken.Intercept(interceptors...)
c.User.Intercept(interceptors...)
}
// Mutate implements the ent.Mutator interface.
func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) {
switch m := m.(type) {
case *PasswordTokenMutation:
return c.PasswordToken.mutate(ctx, m)
case *UserMutation:
return c.User.mutate(ctx, m)
default:
return nil, fmt.Errorf("ent: unknown mutation type %T", m)
}
}
// PasswordTokenClient is a client for the PasswordToken schema.
type PasswordTokenClient struct {
config
}
// NewPasswordTokenClient returns a client for the PasswordToken from the given config.
func NewPasswordTokenClient(c config) *PasswordTokenClient {
return &PasswordTokenClient{config: c}
}
// Use adds a list of mutation hooks to the hooks stack.
// A call to `Use(f, g, h)` equals to `passwordtoken.Hooks(f(g(h())))`.
func (c *PasswordTokenClient) Use(hooks ...Hook) {
c.hooks.PasswordToken = append(c.hooks.PasswordToken, hooks...)
}
// Intercept adds a list of query interceptors to the interceptors stack.
// A call to `Intercept(f, g, h)` equals to `passwordtoken.Intercept(f(g(h())))`.
func (c *PasswordTokenClient) Intercept(interceptors ...Interceptor) {
c.inters.PasswordToken = append(c.inters.PasswordToken, interceptors...)
}
// Create returns a builder for creating a PasswordToken entity.
func (c *PasswordTokenClient) Create() *PasswordTokenCreate {
mutation := newPasswordTokenMutation(c.config, OpCreate)
return &PasswordTokenCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// CreateBulk returns a builder for creating a bulk of PasswordToken entities.
func (c *PasswordTokenClient) CreateBulk(builders ...*PasswordTokenCreate) *PasswordTokenCreateBulk {
return &PasswordTokenCreateBulk{config: c.config, builders: builders}
}
// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates
// a builder and applies setFunc on it.
func (c *PasswordTokenClient) MapCreateBulk(slice any, setFunc func(*PasswordTokenCreate, int)) *PasswordTokenCreateBulk {
rv := reflect.ValueOf(slice)
if rv.Kind() != reflect.Slice {
return &PasswordTokenCreateBulk{err: fmt.Errorf("calling to PasswordTokenClient.MapCreateBulk with wrong type %T, need slice", slice)}
}
builders := make([]*PasswordTokenCreate, rv.Len())
for i := 0; i < rv.Len(); i++ {
builders[i] = c.Create()
setFunc(builders[i], i)
}
return &PasswordTokenCreateBulk{config: c.config, builders: builders}
}
// Update returns an update builder for PasswordToken.
func (c *PasswordTokenClient) Update() *PasswordTokenUpdate {
mutation := newPasswordTokenMutation(c.config, OpUpdate)
return &PasswordTokenUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOne returns an update builder for the given entity.
func (c *PasswordTokenClient) UpdateOne(pt *PasswordToken) *PasswordTokenUpdateOne {
mutation := newPasswordTokenMutation(c.config, OpUpdateOne, withPasswordToken(pt))
return &PasswordTokenUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOneID returns an update builder for the given id.
func (c *PasswordTokenClient) UpdateOneID(id int) *PasswordTokenUpdateOne {
mutation := newPasswordTokenMutation(c.config, OpUpdateOne, withPasswordTokenID(id))
return &PasswordTokenUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// Delete returns a delete builder for PasswordToken.
func (c *PasswordTokenClient) Delete() *PasswordTokenDelete {
mutation := newPasswordTokenMutation(c.config, OpDelete)
return &PasswordTokenDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// DeleteOne returns a builder for deleting the given entity.
func (c *PasswordTokenClient) DeleteOne(pt *PasswordToken) *PasswordTokenDeleteOne {
return c.DeleteOneID(pt.ID)
}
// DeleteOneID returns a builder for deleting the given entity by its id.
func (c *PasswordTokenClient) DeleteOneID(id int) *PasswordTokenDeleteOne {
builder := c.Delete().Where(passwordtoken.ID(id))
builder.mutation.id = &id
builder.mutation.op = OpDeleteOne
return &PasswordTokenDeleteOne{builder}
}
// Query returns a query builder for PasswordToken.
func (c *PasswordTokenClient) Query() *PasswordTokenQuery {
return &PasswordTokenQuery{
config: c.config,
ctx: &QueryContext{Type: TypePasswordToken},
inters: c.Interceptors(),
}
}
// Get returns a PasswordToken entity by its id.
func (c *PasswordTokenClient) Get(ctx context.Context, id int) (*PasswordToken, error) {
return c.Query().Where(passwordtoken.ID(id)).Only(ctx)
}
// GetX is like Get, but panics if an error occurs.
func (c *PasswordTokenClient) GetX(ctx context.Context, id int) *PasswordToken {
obj, err := c.Get(ctx, id)
if err != nil {
panic(err)
}
return obj
}
// QueryUser queries the user edge of a PasswordToken.
func (c *PasswordTokenClient) QueryUser(pt *PasswordToken) *UserQuery {
query := (&UserClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := pt.ID
step := sqlgraph.NewStep(
sqlgraph.From(passwordtoken.Table, passwordtoken.FieldID, id),
sqlgraph.To(user.Table, user.FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, passwordtoken.UserTable, passwordtoken.UserColumn),
)
fromV = sqlgraph.Neighbors(pt.driver.Dialect(), step)
return fromV, nil
}
return query
}
// Hooks returns the client hooks.
func (c *PasswordTokenClient) Hooks() []Hook {
return c.hooks.PasswordToken
}
// Interceptors returns the client interceptors.
func (c *PasswordTokenClient) Interceptors() []Interceptor {
return c.inters.PasswordToken
}
func (c *PasswordTokenClient) mutate(ctx context.Context, m *PasswordTokenMutation) (Value, error) {
switch m.Op() {
case OpCreate:
return (&PasswordTokenCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpUpdate:
return (&PasswordTokenUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpUpdateOne:
return (&PasswordTokenUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpDelete, OpDeleteOne:
return (&PasswordTokenDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
default:
return nil, fmt.Errorf("ent: unknown PasswordToken mutation op: %q", m.Op())
}
}
// UserClient is a client for the User schema.
type UserClient struct {
config
}
// NewUserClient returns a client for the User from the given config.
func NewUserClient(c config) *UserClient {
return &UserClient{config: c}
}
// Use adds a list of mutation hooks to the hooks stack.
// A call to `Use(f, g, h)` equals to `user.Hooks(f(g(h())))`.
func (c *UserClient) Use(hooks ...Hook) {
c.hooks.User = append(c.hooks.User, hooks...)
}
// Intercept adds a list of query interceptors to the interceptors stack.
// A call to `Intercept(f, g, h)` equals to `user.Intercept(f(g(h())))`.
func (c *UserClient) Intercept(interceptors ...Interceptor) {
c.inters.User = append(c.inters.User, interceptors...)
}
// Create returns a builder for creating a User entity.
func (c *UserClient) Create() *UserCreate {
mutation := newUserMutation(c.config, OpCreate)
return &UserCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// CreateBulk returns a builder for creating a bulk of User entities.
func (c *UserClient) CreateBulk(builders ...*UserCreate) *UserCreateBulk {
return &UserCreateBulk{config: c.config, builders: builders}
}
// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates
// a builder and applies setFunc on it.
func (c *UserClient) MapCreateBulk(slice any, setFunc func(*UserCreate, int)) *UserCreateBulk {
rv := reflect.ValueOf(slice)
if rv.Kind() != reflect.Slice {
return &UserCreateBulk{err: fmt.Errorf("calling to UserClient.MapCreateBulk with wrong type %T, need slice", slice)}
}
builders := make([]*UserCreate, rv.Len())
for i := 0; i < rv.Len(); i++ {
builders[i] = c.Create()
setFunc(builders[i], i)
}
return &UserCreateBulk{config: c.config, builders: builders}
}
// Update returns an update builder for User.
func (c *UserClient) Update() *UserUpdate {
mutation := newUserMutation(c.config, OpUpdate)
return &UserUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOne returns an update builder for the given entity.
func (c *UserClient) UpdateOne(u *User) *UserUpdateOne {
mutation := newUserMutation(c.config, OpUpdateOne, withUser(u))
return &UserUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOneID returns an update builder for the given id.
func (c *UserClient) UpdateOneID(id int) *UserUpdateOne {
mutation := newUserMutation(c.config, OpUpdateOne, withUserID(id))
return &UserUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// Delete returns a delete builder for User.
func (c *UserClient) Delete() *UserDelete {
mutation := newUserMutation(c.config, OpDelete)
return &UserDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// DeleteOne returns a builder for deleting the given entity.
func (c *UserClient) DeleteOne(u *User) *UserDeleteOne {
return c.DeleteOneID(u.ID)
}
// DeleteOneID returns a builder for deleting the given entity by its id.
func (c *UserClient) DeleteOneID(id int) *UserDeleteOne {
builder := c.Delete().Where(user.ID(id))
builder.mutation.id = &id
builder.mutation.op = OpDeleteOne
return &UserDeleteOne{builder}
}
// Query returns a query builder for User.
func (c *UserClient) Query() *UserQuery {
return &UserQuery{
config: c.config,
ctx: &QueryContext{Type: TypeUser},
inters: c.Interceptors(),
}
}
// Get returns a User entity by its id.
func (c *UserClient) Get(ctx context.Context, id int) (*User, error) {
return c.Query().Where(user.ID(id)).Only(ctx)
}
// GetX is like Get, but panics if an error occurs.
func (c *UserClient) GetX(ctx context.Context, id int) *User {
obj, err := c.Get(ctx, id)
if err != nil {
panic(err)
}
return obj
}
// QueryOwner queries the owner edge of a User.
func (c *UserClient) QueryOwner(u *User) *PasswordTokenQuery {
query := (&PasswordTokenClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := u.ID
step := sqlgraph.NewStep(
sqlgraph.From(user.Table, user.FieldID, id),
sqlgraph.To(passwordtoken.Table, passwordtoken.FieldID),
sqlgraph.Edge(sqlgraph.O2M, true, user.OwnerTable, user.OwnerColumn),
)
fromV = sqlgraph.Neighbors(u.driver.Dialect(), step)
return fromV, nil
}
return query
}
// Hooks returns the client hooks.
func (c *UserClient) Hooks() []Hook {
hooks := c.hooks.User
return append(hooks[:len(hooks):len(hooks)], user.Hooks[:]...)
}
// Interceptors returns the client interceptors.
func (c *UserClient) Interceptors() []Interceptor {
return c.inters.User
}
func (c *UserClient) mutate(ctx context.Context, m *UserMutation) (Value, error) {
switch m.Op() {
case OpCreate:
return (&UserCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpUpdate:
return (&UserUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpUpdateOne:
return (&UserUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpDelete, OpDeleteOne:
return (&UserDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
default:
return nil, fmt.Errorf("ent: unknown User mutation op: %q", m.Op())
}
}
// hooks and interceptors per client, for fast access.
type (
hooks struct {
PasswordToken, User []ent.Hook
}
inters struct {
PasswordToken, User []ent.Interceptor
}
)

View File

@ -1,611 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"errors"
"fmt"
"reflect"
"sync"
"entgo.io/ent"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"git.grosinger.net/tgrosinger/saasitone/ent/passwordtoken"
"git.grosinger.net/tgrosinger/saasitone/ent/user"
)
// ent aliases to avoid import conflicts in user's code.
type (
Op = ent.Op
Hook = ent.Hook
Value = ent.Value
Query = ent.Query
QueryContext = ent.QueryContext
Querier = ent.Querier
QuerierFunc = ent.QuerierFunc
Interceptor = ent.Interceptor
InterceptFunc = ent.InterceptFunc
Traverser = ent.Traverser
TraverseFunc = ent.TraverseFunc
Policy = ent.Policy
Mutator = ent.Mutator
Mutation = ent.Mutation
MutateFunc = ent.MutateFunc
)
type clientCtxKey struct{}
// FromContext returns a Client stored inside a context, or nil if there isn't one.
func FromContext(ctx context.Context) *Client {
c, _ := ctx.Value(clientCtxKey{}).(*Client)
return c
}
// NewContext returns a new context with the given Client attached.
func NewContext(parent context.Context, c *Client) context.Context {
return context.WithValue(parent, clientCtxKey{}, c)
}
type txCtxKey struct{}
// TxFromContext returns a Tx stored inside a context, or nil if there isn't one.
func TxFromContext(ctx context.Context) *Tx {
tx, _ := ctx.Value(txCtxKey{}).(*Tx)
return tx
}
// NewTxContext returns a new context with the given Tx attached.
func NewTxContext(parent context.Context, tx *Tx) context.Context {
return context.WithValue(parent, txCtxKey{}, tx)
}
// OrderFunc applies an ordering on the sql selector.
// Deprecated: Use Asc/Desc functions or the package builders instead.
type OrderFunc func(*sql.Selector)
var (
initCheck sync.Once
columnCheck sql.ColumnCheck
)
// columnChecker checks if the column exists in the given table.
func checkColumn(table, column string) error {
initCheck.Do(func() {
columnCheck = sql.NewColumnCheck(map[string]func(string) bool{
passwordtoken.Table: passwordtoken.ValidColumn,
user.Table: user.ValidColumn,
})
})
return columnCheck(table, column)
}
// Asc applies the given fields in ASC order.
func Asc(fields ...string) func(*sql.Selector) {
return func(s *sql.Selector) {
for _, f := range fields {
if err := checkColumn(s.TableName(), f); err != nil {
s.AddError(&ValidationError{Name: f, err: fmt.Errorf("ent: %w", err)})
}
s.OrderBy(sql.Asc(s.C(f)))
}
}
}
// Desc applies the given fields in DESC order.
func Desc(fields ...string) func(*sql.Selector) {
return func(s *sql.Selector) {
for _, f := range fields {
if err := checkColumn(s.TableName(), f); err != nil {
s.AddError(&ValidationError{Name: f, err: fmt.Errorf("ent: %w", err)})
}
s.OrderBy(sql.Desc(s.C(f)))
}
}
}
// AggregateFunc applies an aggregation step on the group-by traversal/selector.
type AggregateFunc func(*sql.Selector) string
// As is a pseudo aggregation function for renaming another other functions with custom names. For example:
//
// GroupBy(field1, field2).
// Aggregate(ent.As(ent.Sum(field1), "sum_field1"), (ent.As(ent.Sum(field2), "sum_field2")).
// Scan(ctx, &v)
func As(fn AggregateFunc, end string) AggregateFunc {
return func(s *sql.Selector) string {
return sql.As(fn(s), end)
}
}
// Count applies the "count" aggregation function on each group.
func Count() AggregateFunc {
return func(s *sql.Selector) string {
return sql.Count("*")
}
}
// Max applies the "max" aggregation function on the given field of each group.
func Max(field string) AggregateFunc {
return func(s *sql.Selector) string {
if err := checkColumn(s.TableName(), field); err != nil {
s.AddError(&ValidationError{Name: field, err: fmt.Errorf("ent: %w", err)})
return ""
}
return sql.Max(s.C(field))
}
}
// Mean applies the "mean" aggregation function on the given field of each group.
func Mean(field string) AggregateFunc {
return func(s *sql.Selector) string {
if err := checkColumn(s.TableName(), field); err != nil {
s.AddError(&ValidationError{Name: field, err: fmt.Errorf("ent: %w", err)})
return ""
}
return sql.Avg(s.C(field))
}
}
// Min applies the "min" aggregation function on the given field of each group.
func Min(field string) AggregateFunc {
return func(s *sql.Selector) string {
if err := checkColumn(s.TableName(), field); err != nil {
s.AddError(&ValidationError{Name: field, err: fmt.Errorf("ent: %w", err)})
return ""
}
return sql.Min(s.C(field))
}
}
// Sum applies the "sum" aggregation function on the given field of each group.
func Sum(field string) AggregateFunc {
return func(s *sql.Selector) string {
if err := checkColumn(s.TableName(), field); err != nil {
s.AddError(&ValidationError{Name: field, err: fmt.Errorf("ent: %w", err)})
return ""
}
return sql.Sum(s.C(field))
}
}
// ValidationError returns when validating a field or edge fails.
type ValidationError struct {
Name string // Field or edge name.
err error
}
// Error implements the error interface.
func (e *ValidationError) Error() string {
return e.err.Error()
}
// Unwrap implements the errors.Wrapper interface.
func (e *ValidationError) Unwrap() error {
return e.err
}
// IsValidationError returns a boolean indicating whether the error is a validation error.
func IsValidationError(err error) bool {
if err == nil {
return false
}
var e *ValidationError
return errors.As(err, &e)
}
// NotFoundError returns when trying to fetch a specific entity and it was not found in the database.
type NotFoundError struct {
label string
}
// Error implements the error interface.
func (e *NotFoundError) Error() string {
return "ent: " + e.label + " not found"
}
// IsNotFound returns a boolean indicating whether the error is a not found error.
func IsNotFound(err error) bool {
if err == nil {
return false
}
var e *NotFoundError
return errors.As(err, &e)
}
// MaskNotFound masks not found error.
func MaskNotFound(err error) error {
if IsNotFound(err) {
return nil
}
return err
}
// NotSingularError returns when trying to fetch a singular entity and more then one was found in the database.
type NotSingularError struct {
label string
}
// Error implements the error interface.
func (e *NotSingularError) Error() string {
return "ent: " + e.label + " not singular"
}
// IsNotSingular returns a boolean indicating whether the error is a not singular error.
func IsNotSingular(err error) bool {
if err == nil {
return false
}
var e *NotSingularError
return errors.As(err, &e)
}
// NotLoadedError returns when trying to get a node that was not loaded by the query.
type NotLoadedError struct {
edge string
}
// Error implements the error interface.
func (e *NotLoadedError) Error() string {
return "ent: " + e.edge + " edge was not loaded"
}
// IsNotLoaded returns a boolean indicating whether the error is a not loaded error.
func IsNotLoaded(err error) bool {
if err == nil {
return false
}
var e *NotLoadedError
return errors.As(err, &e)
}
// ConstraintError returns when trying to create/update one or more entities and
// one or more of their constraints failed. For example, violation of edge or
// field uniqueness.
type ConstraintError struct {
msg string
wrap error
}
// Error implements the error interface.
func (e ConstraintError) Error() string {
return "ent: constraint failed: " + e.msg
}
// Unwrap implements the errors.Wrapper interface.
func (e *ConstraintError) Unwrap() error {
return e.wrap
}
// IsConstraintError returns a boolean indicating whether the error is a constraint failure.
func IsConstraintError(err error) bool {
if err == nil {
return false
}
var e *ConstraintError
return errors.As(err, &e)
}
// selector embedded by the different Select/GroupBy builders.
type selector struct {
label string
flds *[]string
fns []AggregateFunc
scan func(context.Context, any) error
}
// ScanX is like Scan, but panics if an error occurs.
func (s *selector) ScanX(ctx context.Context, v any) {
if err := s.scan(ctx, v); err != nil {
panic(err)
}
}
// Strings returns list of strings from a selector. It is only allowed when selecting one field.
func (s *selector) Strings(ctx context.Context) ([]string, error) {
if len(*s.flds) > 1 {
return nil, errors.New("ent: Strings is not achievable when selecting more than 1 field")
}
var v []string
if err := s.scan(ctx, &v); err != nil {
return nil, err
}
return v, nil
}
// StringsX is like Strings, but panics if an error occurs.
func (s *selector) StringsX(ctx context.Context) []string {
v, err := s.Strings(ctx)
if err != nil {
panic(err)
}
return v
}
// String returns a single string from a selector. It is only allowed when selecting one field.
func (s *selector) String(ctx context.Context) (_ string, err error) {
var v []string
if v, err = s.Strings(ctx); err != nil {
return
}
switch len(v) {
case 1:
return v[0], nil
case 0:
err = &NotFoundError{s.label}
default:
err = fmt.Errorf("ent: Strings returned %d results when one was expected", len(v))
}
return
}
// StringX is like String, but panics if an error occurs.
func (s *selector) StringX(ctx context.Context) string {
v, err := s.String(ctx)
if err != nil {
panic(err)
}
return v
}
// Ints returns list of ints from a selector. It is only allowed when selecting one field.
func (s *selector) Ints(ctx context.Context) ([]int, error) {
if len(*s.flds) > 1 {
return nil, errors.New("ent: Ints is not achievable when selecting more than 1 field")
}
var v []int
if err := s.scan(ctx, &v); err != nil {
return nil, err
}
return v, nil
}
// IntsX is like Ints, but panics if an error occurs.
func (s *selector) IntsX(ctx context.Context) []int {
v, err := s.Ints(ctx)
if err != nil {
panic(err)
}
return v
}
// Int returns a single int from a selector. It is only allowed when selecting one field.
func (s *selector) Int(ctx context.Context) (_ int, err error) {
var v []int
if v, err = s.Ints(ctx); err != nil {
return
}
switch len(v) {
case 1:
return v[0], nil
case 0:
err = &NotFoundError{s.label}
default:
err = fmt.Errorf("ent: Ints returned %d results when one was expected", len(v))
}
return
}
// IntX is like Int, but panics if an error occurs.
func (s *selector) IntX(ctx context.Context) int {
v, err := s.Int(ctx)
if err != nil {
panic(err)
}
return v
}
// Float64s returns list of float64s from a selector. It is only allowed when selecting one field.
func (s *selector) Float64s(ctx context.Context) ([]float64, error) {
if len(*s.flds) > 1 {
return nil, errors.New("ent: Float64s is not achievable when selecting more than 1 field")
}
var v []float64
if err := s.scan(ctx, &v); err != nil {
return nil, err
}
return v, nil
}
// Float64sX is like Float64s, but panics if an error occurs.
func (s *selector) Float64sX(ctx context.Context) []float64 {
v, err := s.Float64s(ctx)
if err != nil {
panic(err)
}
return v
}
// Float64 returns a single float64 from a selector. It is only allowed when selecting one field.
func (s *selector) Float64(ctx context.Context) (_ float64, err error) {
var v []float64
if v, err = s.Float64s(ctx); err != nil {
return
}
switch len(v) {
case 1:
return v[0], nil
case 0:
err = &NotFoundError{s.label}
default:
err = fmt.Errorf("ent: Float64s returned %d results when one was expected", len(v))
}
return
}
// Float64X is like Float64, but panics if an error occurs.
func (s *selector) Float64X(ctx context.Context) float64 {
v, err := s.Float64(ctx)
if err != nil {
panic(err)
}
return v
}
// Bools returns list of bools from a selector. It is only allowed when selecting one field.
func (s *selector) Bools(ctx context.Context) ([]bool, error) {
if len(*s.flds) > 1 {
return nil, errors.New("ent: Bools is not achievable when selecting more than 1 field")
}
var v []bool
if err := s.scan(ctx, &v); err != nil {
return nil, err
}
return v, nil
}
// BoolsX is like Bools, but panics if an error occurs.
func (s *selector) BoolsX(ctx context.Context) []bool {
v, err := s.Bools(ctx)
if err != nil {
panic(err)
}
return v
}
// Bool returns a single bool from a selector. It is only allowed when selecting one field.
func (s *selector) Bool(ctx context.Context) (_ bool, err error) {
var v []bool
if v, err = s.Bools(ctx); err != nil {
return
}
switch len(v) {
case 1:
return v[0], nil
case 0:
err = &NotFoundError{s.label}
default:
err = fmt.Errorf("ent: Bools returned %d results when one was expected", len(v))
}
return
}
// BoolX is like Bool, but panics if an error occurs.
func (s *selector) BoolX(ctx context.Context) bool {
v, err := s.Bool(ctx)
if err != nil {
panic(err)
}
return v
}
// withHooks invokes the builder operation with the given hooks, if any.
func withHooks[V Value, M any, PM interface {
*M
Mutation
}](ctx context.Context, exec func(context.Context) (V, error), mutation PM, hooks []Hook) (value V, err error) {
if len(hooks) == 0 {
return exec(ctx)
}
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
mutationT, ok := any(m).(PM)
if !ok {
return nil, fmt.Errorf("unexpected mutation type %T", m)
}
// Set the mutation to the builder.
*mutation = *mutationT
return exec(ctx)
})
for i := len(hooks) - 1; i >= 0; i-- {
if hooks[i] == nil {
return value, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)")
}
mut = hooks[i](mut)
}
v, err := mut.Mutate(ctx, mutation)
if err != nil {
return value, err
}
nv, ok := v.(V)
if !ok {
return value, fmt.Errorf("unexpected node type %T returned from %T", v, mutation)
}
return nv, nil
}
// setContextOp returns a new context with the given QueryContext attached (including its op) in case it does not exist.
func setContextOp(ctx context.Context, qc *QueryContext, op string) context.Context {
if ent.QueryFromContext(ctx) == nil {
qc.Op = op
ctx = ent.NewQueryContext(ctx, qc)
}
return ctx
}
func querierAll[V Value, Q interface {
sqlAll(context.Context, ...queryHook) (V, error)
}]() Querier {
return QuerierFunc(func(ctx context.Context, q Query) (Value, error) {
query, ok := q.(Q)
if !ok {
return nil, fmt.Errorf("unexpected query type %T", q)
}
return query.sqlAll(ctx)
})
}
func querierCount[Q interface {
sqlCount(context.Context) (int, error)
}]() Querier {
return QuerierFunc(func(ctx context.Context, q Query) (Value, error) {
query, ok := q.(Q)
if !ok {
return nil, fmt.Errorf("unexpected query type %T", q)
}
return query.sqlCount(ctx)
})
}
func withInterceptors[V Value](ctx context.Context, q Query, qr Querier, inters []Interceptor) (v V, err error) {
for i := len(inters) - 1; i >= 0; i-- {
qr = inters[i].Intercept(qr)
}
rv, err := qr.Query(ctx, q)
if err != nil {
return v, err
}
vt, ok := rv.(V)
if !ok {
return v, fmt.Errorf("unexpected type %T returned from %T. expected type: %T", vt, q, v)
}
return vt, nil
}
func scanWithInterceptors[Q1 ent.Query, Q2 interface {
sqlScan(context.Context, Q1, any) error
}](ctx context.Context, rootQuery Q1, selectOrGroup Q2, inters []Interceptor, v any) error {
rv := reflect.ValueOf(v)
var qr Querier = QuerierFunc(func(ctx context.Context, q Query) (Value, error) {
query, ok := q.(Q1)
if !ok {
return nil, fmt.Errorf("unexpected query type %T", q)
}
if err := selectOrGroup.sqlScan(ctx, query, v); err != nil {
return nil, err
}
if k := rv.Kind(); k == reflect.Pointer && rv.Elem().CanInterface() {
return rv.Elem().Interface(), nil
}
return v, nil
})
for i := len(inters) - 1; i >= 0; i-- {
qr = inters[i].Intercept(qr)
}
vv, err := qr.Query(ctx, rootQuery)
if err != nil {
return err
}
switch rv2 := reflect.ValueOf(vv); {
case rv.IsNil(), rv2.IsNil(), rv.Kind() != reflect.Pointer:
case rv.Type() == rv2.Type():
rv.Elem().Set(rv2.Elem())
case rv.Elem().Type() == rv2.Type():
rv.Elem().Set(rv2)
}
return nil
}
// queryHook describes an internal hook for the different sqlAll methods.
type queryHook func(context.Context, *sqlgraph.QuerySpec)

View File

@ -1,84 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package enttest
import (
"context"
"entgo.io/ent/dialect/sql/schema"
"git.grosinger.net/tgrosinger/saasitone/ent"
"git.grosinger.net/tgrosinger/saasitone/ent/migrate"
_ "git.grosinger.net/tgrosinger/saasitone/ent/runtime" // required by schema hooks.
)
type (
// TestingT is the interface that is shared between
// testing.T and testing.B and used by enttest.
TestingT interface {
FailNow()
Error(...any)
}
// Option configures client creation.
Option func(*options)
options struct {
opts []ent.Option
migrateOpts []schema.MigrateOption
}
)
// WithOptions forwards options to client creation.
func WithOptions(opts ...ent.Option) Option {
return func(o *options) {
o.opts = append(o.opts, opts...)
}
}
// WithMigrateOptions forwards options to auto migration.
func WithMigrateOptions(opts ...schema.MigrateOption) Option {
return func(o *options) {
o.migrateOpts = append(o.migrateOpts, opts...)
}
}
func newOptions(opts []Option) *options {
o := &options{}
for _, opt := range opts {
opt(o)
}
return o
}
// Open calls ent.Open and auto-run migration.
func Open(t TestingT, driverName, dataSourceName string, opts ...Option) *ent.Client {
o := newOptions(opts)
c, err := ent.Open(driverName, dataSourceName, o.opts...)
if err != nil {
t.Error(err)
t.FailNow()
}
migrateSchema(t, c, o)
return c
}
// NewClient calls ent.NewClient and auto-run migration.
func NewClient(t TestingT, opts ...Option) *ent.Client {
o := newOptions(opts)
c := ent.NewClient(o.opts...)
migrateSchema(t, c, o)
return c
}
func migrateSchema(t TestingT, c *ent.Client, o *options) {
tables, err := schema.CopyTables(migrate.Tables)
if err != nil {
t.Error(err)
t.FailNow()
}
if err := migrate.Create(context.Background(), c.Schema, tables, o.migrateOpts...); err != nil {
t.Error(err)
t.FailNow()
}
}

View File

@ -1,3 +0,0 @@
package ent
//go:generate go run -mod=mod entgo.io/ent/cmd/ent generate ./schema

View File

@ -1,211 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package hook
import (
"context"
"fmt"
"git.grosinger.net/tgrosinger/saasitone/ent"
)
// The PasswordTokenFunc type is an adapter to allow the use of ordinary
// function as PasswordToken mutator.
type PasswordTokenFunc func(context.Context, *ent.PasswordTokenMutation) (ent.Value, error)
// Mutate calls f(ctx, m).
func (f PasswordTokenFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
if mv, ok := m.(*ent.PasswordTokenMutation); ok {
return f(ctx, mv)
}
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.PasswordTokenMutation", m)
}
// The UserFunc type is an adapter to allow the use of ordinary
// function as User mutator.
type UserFunc func(context.Context, *ent.UserMutation) (ent.Value, error)
// Mutate calls f(ctx, m).
func (f UserFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
if mv, ok := m.(*ent.UserMutation); ok {
return f(ctx, mv)
}
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.UserMutation", m)
}
// Condition is a hook condition function.
type Condition func(context.Context, ent.Mutation) bool
// And groups conditions with the AND operator.
func And(first, second Condition, rest ...Condition) Condition {
return func(ctx context.Context, m ent.Mutation) bool {
if !first(ctx, m) || !second(ctx, m) {
return false
}
for _, cond := range rest {
if !cond(ctx, m) {
return false
}
}
return true
}
}
// Or groups conditions with the OR operator.
func Or(first, second Condition, rest ...Condition) Condition {
return func(ctx context.Context, m ent.Mutation) bool {
if first(ctx, m) || second(ctx, m) {
return true
}
for _, cond := range rest {
if cond(ctx, m) {
return true
}
}
return false
}
}
// Not negates a given condition.
func Not(cond Condition) Condition {
return func(ctx context.Context, m ent.Mutation) bool {
return !cond(ctx, m)
}
}
// HasOp is a condition testing mutation operation.
func HasOp(op ent.Op) Condition {
return func(_ context.Context, m ent.Mutation) bool {
return m.Op().Is(op)
}
}
// HasAddedFields is a condition validating `.AddedField` on fields.
func HasAddedFields(field string, fields ...string) Condition {
return func(_ context.Context, m ent.Mutation) bool {
if _, exists := m.AddedField(field); !exists {
return false
}
for _, field := range fields {
if _, exists := m.AddedField(field); !exists {
return false
}
}
return true
}
}
// HasClearedFields is a condition validating `.FieldCleared` on fields.
func HasClearedFields(field string, fields ...string) Condition {
return func(_ context.Context, m ent.Mutation) bool {
if exists := m.FieldCleared(field); !exists {
return false
}
for _, field := range fields {
if exists := m.FieldCleared(field); !exists {
return false
}
}
return true
}
}
// HasFields is a condition validating `.Field` on fields.
func HasFields(field string, fields ...string) Condition {
return func(_ context.Context, m ent.Mutation) bool {
if _, exists := m.Field(field); !exists {
return false
}
for _, field := range fields {
if _, exists := m.Field(field); !exists {
return false
}
}
return true
}
}
// If executes the given hook under condition.
//
// hook.If(ComputeAverage, And(HasFields(...), HasAddedFields(...)))
func If(hk ent.Hook, cond Condition) ent.Hook {
return func(next ent.Mutator) ent.Mutator {
return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) {
if cond(ctx, m) {
return hk(next).Mutate(ctx, m)
}
return next.Mutate(ctx, m)
})
}
}
// On executes the given hook only for the given operation.
//
// hook.On(Log, ent.Delete|ent.Create)
func On(hk ent.Hook, op ent.Op) ent.Hook {
return If(hk, HasOp(op))
}
// Unless skips the given hook only for the given operation.
//
// hook.Unless(Log, ent.Update|ent.UpdateOne)
func Unless(hk ent.Hook, op ent.Op) ent.Hook {
return If(hk, Not(HasOp(op)))
}
// FixedError is a hook returning a fixed error.
func FixedError(err error) ent.Hook {
return func(ent.Mutator) ent.Mutator {
return ent.MutateFunc(func(context.Context, ent.Mutation) (ent.Value, error) {
return nil, err
})
}
}
// Reject returns a hook that rejects all operations that match op.
//
// func (T) Hooks() []ent.Hook {
// return []ent.Hook{
// Reject(ent.Delete|ent.Update),
// }
// }
func Reject(op ent.Op) ent.Hook {
hk := FixedError(fmt.Errorf("%s operation is not allowed", op))
return On(hk, op)
}
// Chain acts as a list of hooks and is effectively immutable.
// Once created, it will always hold the same set of hooks in the same order.
type Chain struct {
hooks []ent.Hook
}
// NewChain creates a new chain of hooks.
func NewChain(hooks ...ent.Hook) Chain {
return Chain{append([]ent.Hook(nil), hooks...)}
}
// Hook chains the list of hooks and returns the final hook.
func (c Chain) Hook() ent.Hook {
return func(mutator ent.Mutator) ent.Mutator {
for i := len(c.hooks) - 1; i >= 0; i-- {
mutator = c.hooks[i](mutator)
}
return mutator
}
}
// Append extends a chain, adding the specified hook
// as the last ones in the mutation flow.
func (c Chain) Append(hooks ...ent.Hook) Chain {
newHooks := make([]ent.Hook, 0, len(c.hooks)+len(hooks))
newHooks = append(newHooks, c.hooks...)
newHooks = append(newHooks, hooks...)
return Chain{newHooks}
}
// Extend extends a chain, adding the specified chain
// as the last ones in the mutation flow.
func (c Chain) Extend(chain Chain) Chain {
return c.Append(chain.hooks...)
}

View File

@ -1,64 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package migrate
import (
"context"
"fmt"
"io"
"entgo.io/ent/dialect"
"entgo.io/ent/dialect/sql/schema"
)
var (
// WithGlobalUniqueID sets the universal ids options to the migration.
// If this option is enabled, ent migration will allocate a 1<<32 range
// for the ids of each entity (table).
// Note that this option cannot be applied on tables that already exist.
WithGlobalUniqueID = schema.WithGlobalUniqueID
// WithDropColumn sets the drop column option to the migration.
// If this option is enabled, ent migration will drop old columns
// that were used for both fields and edges. This defaults to false.
WithDropColumn = schema.WithDropColumn
// WithDropIndex sets the drop index option to the migration.
// If this option is enabled, ent migration will drop old indexes
// that were defined in the schema. This defaults to false.
// Note that unique constraints are defined using `UNIQUE INDEX`,
// and therefore, it's recommended to enable this option to get more
// flexibility in the schema changes.
WithDropIndex = schema.WithDropIndex
// WithForeignKeys enables creating foreign-key in schema DDL. This defaults to true.
WithForeignKeys = schema.WithForeignKeys
)
// Schema is the API for creating, migrating and dropping a schema.
type Schema struct {
drv dialect.Driver
}
// NewSchema creates a new schema client.
func NewSchema(drv dialect.Driver) *Schema { return &Schema{drv: drv} }
// Create creates all schema resources.
func (s *Schema) Create(ctx context.Context, opts ...schema.MigrateOption) error {
return Create(ctx, s, Tables, opts...)
}
// Create creates all table resources using the given schema driver.
func Create(ctx context.Context, s *Schema, tables []*schema.Table, opts ...schema.MigrateOption) error {
migrate, err := schema.NewMigrate(s.drv, opts...)
if err != nil {
return fmt.Errorf("ent/migrate: %w", err)
}
return migrate.Create(ctx, tables...)
}
// WriteTo writes the schema changes to w instead of running them against the database.
//
// if err := client.Schema.WriteTo(context.Background(), os.Stdout); err != nil {
// log.Fatal(err)
// }
func (s *Schema) WriteTo(ctx context.Context, w io.Writer, opts ...schema.MigrateOption) error {
return Create(ctx, &Schema{drv: &schema.WriteDriver{Writer: w, Driver: s.drv}}, Tables, opts...)
}

View File

@ -1,56 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package migrate
import (
"entgo.io/ent/dialect/sql/schema"
"entgo.io/ent/schema/field"
)
var (
// PasswordTokensColumns holds the columns for the "password_tokens" table.
PasswordTokensColumns = []*schema.Column{
{Name: "id", Type: field.TypeInt, Increment: true},
{Name: "hash", Type: field.TypeString},
{Name: "created_at", Type: field.TypeTime},
{Name: "password_token_user", Type: field.TypeInt},
}
// PasswordTokensTable holds the schema information for the "password_tokens" table.
PasswordTokensTable = &schema.Table{
Name: "password_tokens",
Columns: PasswordTokensColumns,
PrimaryKey: []*schema.Column{PasswordTokensColumns[0]},
ForeignKeys: []*schema.ForeignKey{
{
Symbol: "password_tokens_users_user",
Columns: []*schema.Column{PasswordTokensColumns[3]},
RefColumns: []*schema.Column{UsersColumns[0]},
OnDelete: schema.NoAction,
},
},
}
// UsersColumns holds the columns for the "users" table.
UsersColumns = []*schema.Column{
{Name: "id", Type: field.TypeInt, Increment: true},
{Name: "name", Type: field.TypeString},
{Name: "email", Type: field.TypeString, Unique: true},
{Name: "password", Type: field.TypeString},
{Name: "verified", Type: field.TypeBool, Default: false},
{Name: "created_at", Type: field.TypeTime},
}
// UsersTable holds the schema information for the "users" table.
UsersTable = &schema.Table{
Name: "users",
Columns: UsersColumns,
PrimaryKey: []*schema.Column{UsersColumns[0]},
}
// Tables holds all the tables in the schema.
Tables = []*schema.Table{
PasswordTokensTable,
UsersTable,
}
)
func init() {
PasswordTokensTable.ForeignKeys[0].RefTable = UsersTable
}

File diff suppressed because it is too large Load Diff

View File

@ -1,158 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"fmt"
"strings"
"time"
"entgo.io/ent"
"entgo.io/ent/dialect/sql"
"git.grosinger.net/tgrosinger/saasitone/ent/passwordtoken"
"git.grosinger.net/tgrosinger/saasitone/ent/user"
)
// PasswordToken is the model entity for the PasswordToken schema.
type PasswordToken struct {
config `json:"-"`
// ID of the ent.
ID int `json:"id,omitempty"`
// Hash holds the value of the "hash" field.
Hash string `json:"-"`
// CreatedAt holds the value of the "created_at" field.
CreatedAt time.Time `json:"created_at,omitempty"`
// Edges holds the relations/edges for other nodes in the graph.
// The values are being populated by the PasswordTokenQuery when eager-loading is set.
Edges PasswordTokenEdges `json:"edges"`
password_token_user *int
selectValues sql.SelectValues
}
// PasswordTokenEdges holds the relations/edges for other nodes in the graph.
type PasswordTokenEdges struct {
// User holds the value of the user edge.
User *User `json:"user,omitempty"`
// loadedTypes holds the information for reporting if a
// type was loaded (or requested) in eager-loading or not.
loadedTypes [1]bool
}
// UserOrErr returns the User value or an error if the edge
// was not loaded in eager-loading, or loaded but was not found.
func (e PasswordTokenEdges) UserOrErr() (*User, error) {
if e.loadedTypes[0] {
if e.User == nil {
// Edge was loaded but was not found.
return nil, &NotFoundError{label: user.Label}
}
return e.User, nil
}
return nil, &NotLoadedError{edge: "user"}
}
// scanValues returns the types for scanning values from sql.Rows.
func (*PasswordToken) scanValues(columns []string) ([]any, error) {
values := make([]any, len(columns))
for i := range columns {
switch columns[i] {
case passwordtoken.FieldID:
values[i] = new(sql.NullInt64)
case passwordtoken.FieldHash:
values[i] = new(sql.NullString)
case passwordtoken.FieldCreatedAt:
values[i] = new(sql.NullTime)
case passwordtoken.ForeignKeys[0]: // password_token_user
values[i] = new(sql.NullInt64)
default:
values[i] = new(sql.UnknownType)
}
}
return values, nil
}
// assignValues assigns the values that were returned from sql.Rows (after scanning)
// to the PasswordToken fields.
func (pt *PasswordToken) assignValues(columns []string, values []any) error {
if m, n := len(values), len(columns); m < n {
return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
}
for i := range columns {
switch columns[i] {
case passwordtoken.FieldID:
value, ok := values[i].(*sql.NullInt64)
if !ok {
return fmt.Errorf("unexpected type %T for field id", value)
}
pt.ID = int(value.Int64)
case passwordtoken.FieldHash:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field hash", values[i])
} else if value.Valid {
pt.Hash = value.String
}
case passwordtoken.FieldCreatedAt:
if value, ok := values[i].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field created_at", values[i])
} else if value.Valid {
pt.CreatedAt = value.Time
}
case passwordtoken.ForeignKeys[0]:
if value, ok := values[i].(*sql.NullInt64); !ok {
return fmt.Errorf("unexpected type %T for edge-field password_token_user", value)
} else if value.Valid {
pt.password_token_user = new(int)
*pt.password_token_user = int(value.Int64)
}
default:
pt.selectValues.Set(columns[i], values[i])
}
}
return nil
}
// Value returns the ent.Value that was dynamically selected and assigned to the PasswordToken.
// This includes values selected through modifiers, order, etc.
func (pt *PasswordToken) Value(name string) (ent.Value, error) {
return pt.selectValues.Get(name)
}
// QueryUser queries the "user" edge of the PasswordToken entity.
func (pt *PasswordToken) QueryUser() *UserQuery {
return NewPasswordTokenClient(pt.config).QueryUser(pt)
}
// Update returns a builder for updating this PasswordToken.
// Note that you need to call PasswordToken.Unwrap() before calling this method if this PasswordToken
// was returned from a transaction, and the transaction was committed or rolled back.
func (pt *PasswordToken) Update() *PasswordTokenUpdateOne {
return NewPasswordTokenClient(pt.config).UpdateOne(pt)
}
// Unwrap unwraps the PasswordToken entity that was returned from a transaction after it was closed,
// so that all future queries will be executed through the driver which created the transaction.
func (pt *PasswordToken) Unwrap() *PasswordToken {
_tx, ok := pt.config.driver.(*txDriver)
if !ok {
panic("ent: PasswordToken is not a transactional entity")
}
pt.config.driver = _tx.drv
return pt
}
// String implements the fmt.Stringer.
func (pt *PasswordToken) String() string {
var builder strings.Builder
builder.WriteString("PasswordToken(")
builder.WriteString(fmt.Sprintf("id=%v, ", pt.ID))
builder.WriteString("hash=<sensitive>")
builder.WriteString(", ")
builder.WriteString("created_at=")
builder.WriteString(pt.CreatedAt.Format(time.ANSIC))
builder.WriteByte(')')
return builder.String()
}
// PasswordTokens is a parsable slice of PasswordToken.
type PasswordTokens []*PasswordToken

View File

@ -1,99 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package passwordtoken
import (
"time"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
)
const (
// Label holds the string label denoting the passwordtoken type in the database.
Label = "password_token"
// FieldID holds the string denoting the id field in the database.
FieldID = "id"
// FieldHash holds the string denoting the hash field in the database.
FieldHash = "hash"
// FieldCreatedAt holds the string denoting the created_at field in the database.
FieldCreatedAt = "created_at"
// EdgeUser holds the string denoting the user edge name in mutations.
EdgeUser = "user"
// Table holds the table name of the passwordtoken in the database.
Table = "password_tokens"
// UserTable is the table that holds the user relation/edge.
UserTable = "password_tokens"
// UserInverseTable is the table name for the User entity.
// It exists in this package in order to avoid circular dependency with the "user" package.
UserInverseTable = "users"
// UserColumn is the table column denoting the user relation/edge.
UserColumn = "password_token_user"
)
// Columns holds all SQL columns for passwordtoken fields.
var Columns = []string{
FieldID,
FieldHash,
FieldCreatedAt,
}
// ForeignKeys holds the SQL foreign-keys that are owned by the "password_tokens"
// table and are not defined as standalone fields in the schema.
var ForeignKeys = []string{
"password_token_user",
}
// ValidColumn reports if the column name is valid (part of the table columns).
func ValidColumn(column string) bool {
for i := range Columns {
if column == Columns[i] {
return true
}
}
for i := range ForeignKeys {
if column == ForeignKeys[i] {
return true
}
}
return false
}
var (
// HashValidator is a validator for the "hash" field. It is called by the builders before save.
HashValidator func(string) error
// DefaultCreatedAt holds the default value on creation for the "created_at" field.
DefaultCreatedAt func() time.Time
)
// OrderOption defines the ordering options for the PasswordToken queries.
type OrderOption func(*sql.Selector)
// ByID orders the results by the id field.
func ByID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldID, opts...).ToFunc()
}
// ByHash orders the results by the hash field.
func ByHash(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldHash, opts...).ToFunc()
}
// ByCreatedAt orders the results by the created_at field.
func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldCreatedAt, opts...).ToFunc()
}
// ByUserField orders the results by user field.
func ByUserField(field string, opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newUserStep(), sql.OrderByField(field, opts...))
}
}
func newUserStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(UserInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, UserTable, UserColumn),
)
}

View File

@ -1,210 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package passwordtoken
import (
"time"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"git.grosinger.net/tgrosinger/saasitone/ent/predicate"
)
// ID filters vertices based on their ID field.
func ID(id int) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldEQ(FieldID, id))
}
// IDEQ applies the EQ predicate on the ID field.
func IDEQ(id int) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldEQ(FieldID, id))
}
// IDNEQ applies the NEQ predicate on the ID field.
func IDNEQ(id int) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldNEQ(FieldID, id))
}
// IDIn applies the In predicate on the ID field.
func IDIn(ids ...int) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldIn(FieldID, ids...))
}
// IDNotIn applies the NotIn predicate on the ID field.
func IDNotIn(ids ...int) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldNotIn(FieldID, ids...))
}
// IDGT applies the GT predicate on the ID field.
func IDGT(id int) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldGT(FieldID, id))
}
// IDGTE applies the GTE predicate on the ID field.
func IDGTE(id int) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldGTE(FieldID, id))
}
// IDLT applies the LT predicate on the ID field.
func IDLT(id int) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldLT(FieldID, id))
}
// IDLTE applies the LTE predicate on the ID field.
func IDLTE(id int) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldLTE(FieldID, id))
}
// Hash applies equality check predicate on the "hash" field. It's identical to HashEQ.
func Hash(v string) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldEQ(FieldHash, v))
}
// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
func CreatedAt(v time.Time) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldEQ(FieldCreatedAt, v))
}
// HashEQ applies the EQ predicate on the "hash" field.
func HashEQ(v string) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldEQ(FieldHash, v))
}
// HashNEQ applies the NEQ predicate on the "hash" field.
func HashNEQ(v string) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldNEQ(FieldHash, v))
}
// HashIn applies the In predicate on the "hash" field.
func HashIn(vs ...string) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldIn(FieldHash, vs...))
}
// HashNotIn applies the NotIn predicate on the "hash" field.
func HashNotIn(vs ...string) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldNotIn(FieldHash, vs...))
}
// HashGT applies the GT predicate on the "hash" field.
func HashGT(v string) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldGT(FieldHash, v))
}
// HashGTE applies the GTE predicate on the "hash" field.
func HashGTE(v string) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldGTE(FieldHash, v))
}
// HashLT applies the LT predicate on the "hash" field.
func HashLT(v string) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldLT(FieldHash, v))
}
// HashLTE applies the LTE predicate on the "hash" field.
func HashLTE(v string) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldLTE(FieldHash, v))
}
// HashContains applies the Contains predicate on the "hash" field.
func HashContains(v string) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldContains(FieldHash, v))
}
// HashHasPrefix applies the HasPrefix predicate on the "hash" field.
func HashHasPrefix(v string) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldHasPrefix(FieldHash, v))
}
// HashHasSuffix applies the HasSuffix predicate on the "hash" field.
func HashHasSuffix(v string) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldHasSuffix(FieldHash, v))
}
// HashEqualFold applies the EqualFold predicate on the "hash" field.
func HashEqualFold(v string) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldEqualFold(FieldHash, v))
}
// HashContainsFold applies the ContainsFold predicate on the "hash" field.
func HashContainsFold(v string) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldContainsFold(FieldHash, v))
}
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
func CreatedAtEQ(v time.Time) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldEQ(FieldCreatedAt, v))
}
// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
func CreatedAtNEQ(v time.Time) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldNEQ(FieldCreatedAt, v))
}
// CreatedAtIn applies the In predicate on the "created_at" field.
func CreatedAtIn(vs ...time.Time) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldIn(FieldCreatedAt, vs...))
}
// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
func CreatedAtNotIn(vs ...time.Time) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldNotIn(FieldCreatedAt, vs...))
}
// CreatedAtGT applies the GT predicate on the "created_at" field.
func CreatedAtGT(v time.Time) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldGT(FieldCreatedAt, v))
}
// CreatedAtGTE applies the GTE predicate on the "created_at" field.
func CreatedAtGTE(v time.Time) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldGTE(FieldCreatedAt, v))
}
// CreatedAtLT applies the LT predicate on the "created_at" field.
func CreatedAtLT(v time.Time) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldLT(FieldCreatedAt, v))
}
// CreatedAtLTE applies the LTE predicate on the "created_at" field.
func CreatedAtLTE(v time.Time) predicate.PasswordToken {
return predicate.PasswordToken(sql.FieldLTE(FieldCreatedAt, v))
}
// HasUser applies the HasEdge predicate on the "user" edge.
func HasUser() predicate.PasswordToken {
return predicate.PasswordToken(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, UserTable, UserColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasUserWith applies the HasEdge predicate on the "user" edge with a given conditions (other predicates).
func HasUserWith(preds ...predicate.User) predicate.PasswordToken {
return predicate.PasswordToken(func(s *sql.Selector) {
step := newUserStep()
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
p(s)
}
})
})
}
// And groups predicates with the AND operator between them.
func And(predicates ...predicate.PasswordToken) predicate.PasswordToken {
return predicate.PasswordToken(sql.AndPredicates(predicates...))
}
// Or groups predicates with the OR operator between them.
func Or(predicates ...predicate.PasswordToken) predicate.PasswordToken {
return predicate.PasswordToken(sql.OrPredicates(predicates...))
}
// Not applies the not operator on the given predicate.
func Not(p predicate.PasswordToken) predicate.PasswordToken {
return predicate.PasswordToken(sql.NotPredicates(p))
}

View File

@ -1,253 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"errors"
"fmt"
"time"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"git.grosinger.net/tgrosinger/saasitone/ent/passwordtoken"
"git.grosinger.net/tgrosinger/saasitone/ent/user"
)
// PasswordTokenCreate is the builder for creating a PasswordToken entity.
type PasswordTokenCreate struct {
config
mutation *PasswordTokenMutation
hooks []Hook
}
// SetHash sets the "hash" field.
func (ptc *PasswordTokenCreate) SetHash(s string) *PasswordTokenCreate {
ptc.mutation.SetHash(s)
return ptc
}
// SetCreatedAt sets the "created_at" field.
func (ptc *PasswordTokenCreate) SetCreatedAt(t time.Time) *PasswordTokenCreate {
ptc.mutation.SetCreatedAt(t)
return ptc
}
// SetNillableCreatedAt sets the "created_at" field if the given value is not nil.
func (ptc *PasswordTokenCreate) SetNillableCreatedAt(t *time.Time) *PasswordTokenCreate {
if t != nil {
ptc.SetCreatedAt(*t)
}
return ptc
}
// SetUserID sets the "user" edge to the User entity by ID.
func (ptc *PasswordTokenCreate) SetUserID(id int) *PasswordTokenCreate {
ptc.mutation.SetUserID(id)
return ptc
}
// SetUser sets the "user" edge to the User entity.
func (ptc *PasswordTokenCreate) SetUser(u *User) *PasswordTokenCreate {
return ptc.SetUserID(u.ID)
}
// Mutation returns the PasswordTokenMutation object of the builder.
func (ptc *PasswordTokenCreate) Mutation() *PasswordTokenMutation {
return ptc.mutation
}
// Save creates the PasswordToken in the database.
func (ptc *PasswordTokenCreate) Save(ctx context.Context) (*PasswordToken, error) {
ptc.defaults()
return withHooks(ctx, ptc.sqlSave, ptc.mutation, ptc.hooks)
}
// SaveX calls Save and panics if Save returns an error.
func (ptc *PasswordTokenCreate) SaveX(ctx context.Context) *PasswordToken {
v, err := ptc.Save(ctx)
if err != nil {
panic(err)
}
return v
}
// Exec executes the query.
func (ptc *PasswordTokenCreate) Exec(ctx context.Context) error {
_, err := ptc.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (ptc *PasswordTokenCreate) ExecX(ctx context.Context) {
if err := ptc.Exec(ctx); err != nil {
panic(err)
}
}
// defaults sets the default values of the builder before save.
func (ptc *PasswordTokenCreate) defaults() {
if _, ok := ptc.mutation.CreatedAt(); !ok {
v := passwordtoken.DefaultCreatedAt()
ptc.mutation.SetCreatedAt(v)
}
}
// check runs all checks and user-defined validators on the builder.
func (ptc *PasswordTokenCreate) check() error {
if _, ok := ptc.mutation.Hash(); !ok {
return &ValidationError{Name: "hash", err: errors.New(`ent: missing required field "PasswordToken.hash"`)}
}
if v, ok := ptc.mutation.Hash(); ok {
if err := passwordtoken.HashValidator(v); err != nil {
return &ValidationError{Name: "hash", err: fmt.Errorf(`ent: validator failed for field "PasswordToken.hash": %w`, err)}
}
}
if _, ok := ptc.mutation.CreatedAt(); !ok {
return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "PasswordToken.created_at"`)}
}
if _, ok := ptc.mutation.UserID(); !ok {
return &ValidationError{Name: "user", err: errors.New(`ent: missing required edge "PasswordToken.user"`)}
}
return nil
}
func (ptc *PasswordTokenCreate) sqlSave(ctx context.Context) (*PasswordToken, error) {
if err := ptc.check(); err != nil {
return nil, err
}
_node, _spec := ptc.createSpec()
if err := sqlgraph.CreateNode(ctx, ptc.driver, _spec); err != nil {
if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
return nil, err
}
id := _spec.ID.Value.(int64)
_node.ID = int(id)
ptc.mutation.id = &_node.ID
ptc.mutation.done = true
return _node, nil
}
func (ptc *PasswordTokenCreate) createSpec() (*PasswordToken, *sqlgraph.CreateSpec) {
var (
_node = &PasswordToken{config: ptc.config}
_spec = sqlgraph.NewCreateSpec(passwordtoken.Table, sqlgraph.NewFieldSpec(passwordtoken.FieldID, field.TypeInt))
)
if value, ok := ptc.mutation.Hash(); ok {
_spec.SetField(passwordtoken.FieldHash, field.TypeString, value)
_node.Hash = value
}
if value, ok := ptc.mutation.CreatedAt(); ok {
_spec.SetField(passwordtoken.FieldCreatedAt, field.TypeTime, value)
_node.CreatedAt = value
}
if nodes := ptc.mutation.UserIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: passwordtoken.UserTable,
Columns: []string{passwordtoken.UserColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_node.password_token_user = &nodes[0]
_spec.Edges = append(_spec.Edges, edge)
}
return _node, _spec
}
// PasswordTokenCreateBulk is the builder for creating many PasswordToken entities in bulk.
type PasswordTokenCreateBulk struct {
config
err error
builders []*PasswordTokenCreate
}
// Save creates the PasswordToken entities in the database.
func (ptcb *PasswordTokenCreateBulk) Save(ctx context.Context) ([]*PasswordToken, error) {
if ptcb.err != nil {
return nil, ptcb.err
}
specs := make([]*sqlgraph.CreateSpec, len(ptcb.builders))
nodes := make([]*PasswordToken, len(ptcb.builders))
mutators := make([]Mutator, len(ptcb.builders))
for i := range ptcb.builders {
func(i int, root context.Context) {
builder := ptcb.builders[i]
builder.defaults()
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
mutation, ok := m.(*PasswordTokenMutation)
if !ok {
return nil, fmt.Errorf("unexpected mutation type %T", m)
}
if err := builder.check(); err != nil {
return nil, err
}
builder.mutation = mutation
var err error
nodes[i], specs[i] = builder.createSpec()
if i < len(mutators)-1 {
_, err = mutators[i+1].Mutate(root, ptcb.builders[i+1].mutation)
} else {
spec := &sqlgraph.BatchCreateSpec{Nodes: specs}
// Invoke the actual operation on the latest mutation in the chain.
if err = sqlgraph.BatchCreate(ctx, ptcb.driver, spec); err != nil {
if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
}
}
if err != nil {
return nil, err
}
mutation.id = &nodes[i].ID
if specs[i].ID.Value != nil {
id := specs[i].ID.Value.(int64)
nodes[i].ID = int(id)
}
mutation.done = true
return nodes[i], nil
})
for i := len(builder.hooks) - 1; i >= 0; i-- {
mut = builder.hooks[i](mut)
}
mutators[i] = mut
}(i, ctx)
}
if len(mutators) > 0 {
if _, err := mutators[0].Mutate(ctx, ptcb.builders[0].mutation); err != nil {
return nil, err
}
}
return nodes, nil
}
// SaveX is like Save, but panics if an error occurs.
func (ptcb *PasswordTokenCreateBulk) SaveX(ctx context.Context) []*PasswordToken {
v, err := ptcb.Save(ctx)
if err != nil {
panic(err)
}
return v
}
// Exec executes the query.
func (ptcb *PasswordTokenCreateBulk) Exec(ctx context.Context) error {
_, err := ptcb.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (ptcb *PasswordTokenCreateBulk) ExecX(ctx context.Context) {
if err := ptcb.Exec(ctx); err != nil {
panic(err)
}
}

View File

@ -1,89 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"git.grosinger.net/tgrosinger/saasitone/ent/passwordtoken"
"git.grosinger.net/tgrosinger/saasitone/ent/predicate"
)
// PasswordTokenDelete is the builder for deleting a PasswordToken entity.
type PasswordTokenDelete struct {
config
hooks []Hook
mutation *PasswordTokenMutation
}
// Where appends a list predicates to the PasswordTokenDelete builder.
func (ptd *PasswordTokenDelete) Where(ps ...predicate.PasswordToken) *PasswordTokenDelete {
ptd.mutation.Where(ps...)
return ptd
}
// Exec executes the deletion query and returns how many vertices were deleted.
func (ptd *PasswordTokenDelete) Exec(ctx context.Context) (int, error) {
return withHooks(ctx, ptd.sqlExec, ptd.mutation, ptd.hooks)
}
// ExecX is like Exec, but panics if an error occurs.
func (ptd *PasswordTokenDelete) ExecX(ctx context.Context) int {
n, err := ptd.Exec(ctx)
if err != nil {
panic(err)
}
return n
}
func (ptd *PasswordTokenDelete) sqlExec(ctx context.Context) (int, error) {
_spec := sqlgraph.NewDeleteSpec(passwordtoken.Table, sqlgraph.NewFieldSpec(passwordtoken.FieldID, field.TypeInt))
if ps := ptd.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
affected, err := sqlgraph.DeleteNodes(ctx, ptd.driver, _spec)
if err != nil && sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
ptd.mutation.done = true
return affected, err
}
// PasswordTokenDeleteOne is the builder for deleting a single PasswordToken entity.
type PasswordTokenDeleteOne struct {
ptd *PasswordTokenDelete
}
// Where appends a list predicates to the PasswordTokenDelete builder.
func (ptdo *PasswordTokenDeleteOne) Where(ps ...predicate.PasswordToken) *PasswordTokenDeleteOne {
ptdo.ptd.mutation.Where(ps...)
return ptdo
}
// Exec executes the deletion query.
func (ptdo *PasswordTokenDeleteOne) Exec(ctx context.Context) error {
n, err := ptdo.ptd.Exec(ctx)
switch {
case err != nil:
return err
case n == 0:
return &NotFoundError{passwordtoken.Label}
default:
return nil
}
}
// ExecX is like Exec, but panics if an error occurs.
func (ptdo *PasswordTokenDeleteOne) ExecX(ctx context.Context) {
if err := ptdo.Exec(ctx); err != nil {
panic(err)
}
}

View File

@ -1,614 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"fmt"
"math"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"git.grosinger.net/tgrosinger/saasitone/ent/passwordtoken"
"git.grosinger.net/tgrosinger/saasitone/ent/predicate"
"git.grosinger.net/tgrosinger/saasitone/ent/user"
)
// PasswordTokenQuery is the builder for querying PasswordToken entities.
type PasswordTokenQuery struct {
config
ctx *QueryContext
order []passwordtoken.OrderOption
inters []Interceptor
predicates []predicate.PasswordToken
withUser *UserQuery
withFKs bool
// intermediate query (i.e. traversal path).
sql *sql.Selector
path func(context.Context) (*sql.Selector, error)
}
// Where adds a new predicate for the PasswordTokenQuery builder.
func (ptq *PasswordTokenQuery) Where(ps ...predicate.PasswordToken) *PasswordTokenQuery {
ptq.predicates = append(ptq.predicates, ps...)
return ptq
}
// Limit the number of records to be returned by this query.
func (ptq *PasswordTokenQuery) Limit(limit int) *PasswordTokenQuery {
ptq.ctx.Limit = &limit
return ptq
}
// Offset to start from.
func (ptq *PasswordTokenQuery) Offset(offset int) *PasswordTokenQuery {
ptq.ctx.Offset = &offset
return ptq
}
// Unique configures the query builder to filter duplicate records on query.
// By default, unique is set to true, and can be disabled using this method.
func (ptq *PasswordTokenQuery) Unique(unique bool) *PasswordTokenQuery {
ptq.ctx.Unique = &unique
return ptq
}
// Order specifies how the records should be ordered.
func (ptq *PasswordTokenQuery) Order(o ...passwordtoken.OrderOption) *PasswordTokenQuery {
ptq.order = append(ptq.order, o...)
return ptq
}
// QueryUser chains the current query on the "user" edge.
func (ptq *PasswordTokenQuery) QueryUser() *UserQuery {
query := (&UserClient{config: ptq.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := ptq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := ptq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(passwordtoken.Table, passwordtoken.FieldID, selector),
sqlgraph.To(user.Table, user.FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, passwordtoken.UserTable, passwordtoken.UserColumn),
)
fromU = sqlgraph.SetNeighbors(ptq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// First returns the first PasswordToken entity from the query.
// Returns a *NotFoundError when no PasswordToken was found.
func (ptq *PasswordTokenQuery) First(ctx context.Context) (*PasswordToken, error) {
nodes, err := ptq.Limit(1).All(setContextOp(ctx, ptq.ctx, "First"))
if err != nil {
return nil, err
}
if len(nodes) == 0 {
return nil, &NotFoundError{passwordtoken.Label}
}
return nodes[0], nil
}
// FirstX is like First, but panics if an error occurs.
func (ptq *PasswordTokenQuery) FirstX(ctx context.Context) *PasswordToken {
node, err := ptq.First(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return node
}
// FirstID returns the first PasswordToken ID from the query.
// Returns a *NotFoundError when no PasswordToken ID was found.
func (ptq *PasswordTokenQuery) FirstID(ctx context.Context) (id int, err error) {
var ids []int
if ids, err = ptq.Limit(1).IDs(setContextOp(ctx, ptq.ctx, "FirstID")); err != nil {
return
}
if len(ids) == 0 {
err = &NotFoundError{passwordtoken.Label}
return
}
return ids[0], nil
}
// FirstIDX is like FirstID, but panics if an error occurs.
func (ptq *PasswordTokenQuery) FirstIDX(ctx context.Context) int {
id, err := ptq.FirstID(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return id
}
// Only returns a single PasswordToken entity found by the query, ensuring it only returns one.
// Returns a *NotSingularError when more than one PasswordToken entity is found.
// Returns a *NotFoundError when no PasswordToken entities are found.
func (ptq *PasswordTokenQuery) Only(ctx context.Context) (*PasswordToken, error) {
nodes, err := ptq.Limit(2).All(setContextOp(ctx, ptq.ctx, "Only"))
if err != nil {
return nil, err
}
switch len(nodes) {
case 1:
return nodes[0], nil
case 0:
return nil, &NotFoundError{passwordtoken.Label}
default:
return nil, &NotSingularError{passwordtoken.Label}
}
}
// OnlyX is like Only, but panics if an error occurs.
func (ptq *PasswordTokenQuery) OnlyX(ctx context.Context) *PasswordToken {
node, err := ptq.Only(ctx)
if err != nil {
panic(err)
}
return node
}
// OnlyID is like Only, but returns the only PasswordToken ID in the query.
// Returns a *NotSingularError when more than one PasswordToken ID is found.
// Returns a *NotFoundError when no entities are found.
func (ptq *PasswordTokenQuery) OnlyID(ctx context.Context) (id int, err error) {
var ids []int
if ids, err = ptq.Limit(2).IDs(setContextOp(ctx, ptq.ctx, "OnlyID")); err != nil {
return
}
switch len(ids) {
case 1:
id = ids[0]
case 0:
err = &NotFoundError{passwordtoken.Label}
default:
err = &NotSingularError{passwordtoken.Label}
}
return
}
// OnlyIDX is like OnlyID, but panics if an error occurs.
func (ptq *PasswordTokenQuery) OnlyIDX(ctx context.Context) int {
id, err := ptq.OnlyID(ctx)
if err != nil {
panic(err)
}
return id
}
// All executes the query and returns a list of PasswordTokens.
func (ptq *PasswordTokenQuery) All(ctx context.Context) ([]*PasswordToken, error) {
ctx = setContextOp(ctx, ptq.ctx, "All")
if err := ptq.prepareQuery(ctx); err != nil {
return nil, err
}
qr := querierAll[[]*PasswordToken, *PasswordTokenQuery]()
return withInterceptors[[]*PasswordToken](ctx, ptq, qr, ptq.inters)
}
// AllX is like All, but panics if an error occurs.
func (ptq *PasswordTokenQuery) AllX(ctx context.Context) []*PasswordToken {
nodes, err := ptq.All(ctx)
if err != nil {
panic(err)
}
return nodes
}
// IDs executes the query and returns a list of PasswordToken IDs.
func (ptq *PasswordTokenQuery) IDs(ctx context.Context) (ids []int, err error) {
if ptq.ctx.Unique == nil && ptq.path != nil {
ptq.Unique(true)
}
ctx = setContextOp(ctx, ptq.ctx, "IDs")
if err = ptq.Select(passwordtoken.FieldID).Scan(ctx, &ids); err != nil {
return nil, err
}
return ids, nil
}
// IDsX is like IDs, but panics if an error occurs.
func (ptq *PasswordTokenQuery) IDsX(ctx context.Context) []int {
ids, err := ptq.IDs(ctx)
if err != nil {
panic(err)
}
return ids
}
// Count returns the count of the given query.
func (ptq *PasswordTokenQuery) Count(ctx context.Context) (int, error) {
ctx = setContextOp(ctx, ptq.ctx, "Count")
if err := ptq.prepareQuery(ctx); err != nil {
return 0, err
}
return withInterceptors[int](ctx, ptq, querierCount[*PasswordTokenQuery](), ptq.inters)
}
// CountX is like Count, but panics if an error occurs.
func (ptq *PasswordTokenQuery) CountX(ctx context.Context) int {
count, err := ptq.Count(ctx)
if err != nil {
panic(err)
}
return count
}
// Exist returns true if the query has elements in the graph.
func (ptq *PasswordTokenQuery) Exist(ctx context.Context) (bool, error) {
ctx = setContextOp(ctx, ptq.ctx, "Exist")
switch _, err := ptq.FirstID(ctx); {
case IsNotFound(err):
return false, nil
case err != nil:
return false, fmt.Errorf("ent: check existence: %w", err)
default:
return true, nil
}
}
// ExistX is like Exist, but panics if an error occurs.
func (ptq *PasswordTokenQuery) ExistX(ctx context.Context) bool {
exist, err := ptq.Exist(ctx)
if err != nil {
panic(err)
}
return exist
}
// Clone returns a duplicate of the PasswordTokenQuery builder, including all associated steps. It can be
// used to prepare common query builders and use them differently after the clone is made.
func (ptq *PasswordTokenQuery) Clone() *PasswordTokenQuery {
if ptq == nil {
return nil
}
return &PasswordTokenQuery{
config: ptq.config,
ctx: ptq.ctx.Clone(),
order: append([]passwordtoken.OrderOption{}, ptq.order...),
inters: append([]Interceptor{}, ptq.inters...),
predicates: append([]predicate.PasswordToken{}, ptq.predicates...),
withUser: ptq.withUser.Clone(),
// clone intermediate query.
sql: ptq.sql.Clone(),
path: ptq.path,
}
}
// WithUser tells the query-builder to eager-load the nodes that are connected to
// the "user" edge. The optional arguments are used to configure the query builder of the edge.
func (ptq *PasswordTokenQuery) WithUser(opts ...func(*UserQuery)) *PasswordTokenQuery {
query := (&UserClient{config: ptq.config}).Query()
for _, opt := range opts {
opt(query)
}
ptq.withUser = query
return ptq
}
// GroupBy is used to group vertices by one or more fields/columns.
// It is often used with aggregate functions, like: count, max, mean, min, sum.
//
// Example:
//
// var v []struct {
// Hash string `json:"hash,omitempty"`
// Count int `json:"count,omitempty"`
// }
//
// client.PasswordToken.Query().
// GroupBy(passwordtoken.FieldHash).
// Aggregate(ent.Count()).
// Scan(ctx, &v)
func (ptq *PasswordTokenQuery) GroupBy(field string, fields ...string) *PasswordTokenGroupBy {
ptq.ctx.Fields = append([]string{field}, fields...)
grbuild := &PasswordTokenGroupBy{build: ptq}
grbuild.flds = &ptq.ctx.Fields
grbuild.label = passwordtoken.Label
grbuild.scan = grbuild.Scan
return grbuild
}
// Select allows the selection one or more fields/columns for the given query,
// instead of selecting all fields in the entity.
//
// Example:
//
// var v []struct {
// Hash string `json:"hash,omitempty"`
// }
//
// client.PasswordToken.Query().
// Select(passwordtoken.FieldHash).
// Scan(ctx, &v)
func (ptq *PasswordTokenQuery) Select(fields ...string) *PasswordTokenSelect {
ptq.ctx.Fields = append(ptq.ctx.Fields, fields...)
sbuild := &PasswordTokenSelect{PasswordTokenQuery: ptq}
sbuild.label = passwordtoken.Label
sbuild.flds, sbuild.scan = &ptq.ctx.Fields, sbuild.Scan
return sbuild
}
// Aggregate returns a PasswordTokenSelect configured with the given aggregations.
func (ptq *PasswordTokenQuery) Aggregate(fns ...AggregateFunc) *PasswordTokenSelect {
return ptq.Select().Aggregate(fns...)
}
func (ptq *PasswordTokenQuery) prepareQuery(ctx context.Context) error {
for _, inter := range ptq.inters {
if inter == nil {
return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)")
}
if trv, ok := inter.(Traverser); ok {
if err := trv.Traverse(ctx, ptq); err != nil {
return err
}
}
}
for _, f := range ptq.ctx.Fields {
if !passwordtoken.ValidColumn(f) {
return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
}
}
if ptq.path != nil {
prev, err := ptq.path(ctx)
if err != nil {
return err
}
ptq.sql = prev
}
return nil
}
func (ptq *PasswordTokenQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*PasswordToken, error) {
var (
nodes = []*PasswordToken{}
withFKs = ptq.withFKs
_spec = ptq.querySpec()
loadedTypes = [1]bool{
ptq.withUser != nil,
}
)
if ptq.withUser != nil {
withFKs = true
}
if withFKs {
_spec.Node.Columns = append(_spec.Node.Columns, passwordtoken.ForeignKeys...)
}
_spec.ScanValues = func(columns []string) ([]any, error) {
return (*PasswordToken).scanValues(nil, columns)
}
_spec.Assign = func(columns []string, values []any) error {
node := &PasswordToken{config: ptq.config}
nodes = append(nodes, node)
node.Edges.loadedTypes = loadedTypes
return node.assignValues(columns, values)
}
for i := range hooks {
hooks[i](ctx, _spec)
}
if err := sqlgraph.QueryNodes(ctx, ptq.driver, _spec); err != nil {
return nil, err
}
if len(nodes) == 0 {
return nodes, nil
}
if query := ptq.withUser; query != nil {
if err := ptq.loadUser(ctx, query, nodes, nil,
func(n *PasswordToken, e *User) { n.Edges.User = e }); err != nil {
return nil, err
}
}
return nodes, nil
}
func (ptq *PasswordTokenQuery) loadUser(ctx context.Context, query *UserQuery, nodes []*PasswordToken, init func(*PasswordToken), assign func(*PasswordToken, *User)) error {
ids := make([]int, 0, len(nodes))
nodeids := make(map[int][]*PasswordToken)
for i := range nodes {
if nodes[i].password_token_user == nil {
continue
}
fk := *nodes[i].password_token_user
if _, ok := nodeids[fk]; !ok {
ids = append(ids, fk)
}
nodeids[fk] = append(nodeids[fk], nodes[i])
}
if len(ids) == 0 {
return nil
}
query.Where(user.IDIn(ids...))
neighbors, err := query.All(ctx)
if err != nil {
return err
}
for _, n := range neighbors {
nodes, ok := nodeids[n.ID]
if !ok {
return fmt.Errorf(`unexpected foreign-key "password_token_user" returned %v`, n.ID)
}
for i := range nodes {
assign(nodes[i], n)
}
}
return nil
}
func (ptq *PasswordTokenQuery) sqlCount(ctx context.Context) (int, error) {
_spec := ptq.querySpec()
_spec.Node.Columns = ptq.ctx.Fields
if len(ptq.ctx.Fields) > 0 {
_spec.Unique = ptq.ctx.Unique != nil && *ptq.ctx.Unique
}
return sqlgraph.CountNodes(ctx, ptq.driver, _spec)
}
func (ptq *PasswordTokenQuery) querySpec() *sqlgraph.QuerySpec {
_spec := sqlgraph.NewQuerySpec(passwordtoken.Table, passwordtoken.Columns, sqlgraph.NewFieldSpec(passwordtoken.FieldID, field.TypeInt))
_spec.From = ptq.sql
if unique := ptq.ctx.Unique; unique != nil {
_spec.Unique = *unique
} else if ptq.path != nil {
_spec.Unique = true
}
if fields := ptq.ctx.Fields; len(fields) > 0 {
_spec.Node.Columns = make([]string, 0, len(fields))
_spec.Node.Columns = append(_spec.Node.Columns, passwordtoken.FieldID)
for i := range fields {
if fields[i] != passwordtoken.FieldID {
_spec.Node.Columns = append(_spec.Node.Columns, fields[i])
}
}
}
if ps := ptq.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if limit := ptq.ctx.Limit; limit != nil {
_spec.Limit = *limit
}
if offset := ptq.ctx.Offset; offset != nil {
_spec.Offset = *offset
}
if ps := ptq.order; len(ps) > 0 {
_spec.Order = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
return _spec
}
func (ptq *PasswordTokenQuery) sqlQuery(ctx context.Context) *sql.Selector {
builder := sql.Dialect(ptq.driver.Dialect())
t1 := builder.Table(passwordtoken.Table)
columns := ptq.ctx.Fields
if len(columns) == 0 {
columns = passwordtoken.Columns
}
selector := builder.Select(t1.Columns(columns...)...).From(t1)
if ptq.sql != nil {
selector = ptq.sql
selector.Select(selector.Columns(columns...)...)
}
if ptq.ctx.Unique != nil && *ptq.ctx.Unique {
selector.Distinct()
}
for _, p := range ptq.predicates {
p(selector)
}
for _, p := range ptq.order {
p(selector)
}
if offset := ptq.ctx.Offset; offset != nil {
// limit is mandatory for offset clause. We start
// with default value, and override it below if needed.
selector.Offset(*offset).Limit(math.MaxInt32)
}
if limit := ptq.ctx.Limit; limit != nil {
selector.Limit(*limit)
}
return selector
}
// PasswordTokenGroupBy is the group-by builder for PasswordToken entities.
type PasswordTokenGroupBy struct {
selector
build *PasswordTokenQuery
}
// Aggregate adds the given aggregation functions to the group-by query.
func (ptgb *PasswordTokenGroupBy) Aggregate(fns ...AggregateFunc) *PasswordTokenGroupBy {
ptgb.fns = append(ptgb.fns, fns...)
return ptgb
}
// Scan applies the selector query and scans the result into the given value.
func (ptgb *PasswordTokenGroupBy) Scan(ctx context.Context, v any) error {
ctx = setContextOp(ctx, ptgb.build.ctx, "GroupBy")
if err := ptgb.build.prepareQuery(ctx); err != nil {
return err
}
return scanWithInterceptors[*PasswordTokenQuery, *PasswordTokenGroupBy](ctx, ptgb.build, ptgb, ptgb.build.inters, v)
}
func (ptgb *PasswordTokenGroupBy) sqlScan(ctx context.Context, root *PasswordTokenQuery, v any) error {
selector := root.sqlQuery(ctx).Select()
aggregation := make([]string, 0, len(ptgb.fns))
for _, fn := range ptgb.fns {
aggregation = append(aggregation, fn(selector))
}
if len(selector.SelectedColumns()) == 0 {
columns := make([]string, 0, len(*ptgb.flds)+len(ptgb.fns))
for _, f := range *ptgb.flds {
columns = append(columns, selector.C(f))
}
columns = append(columns, aggregation...)
selector.Select(columns...)
}
selector.GroupBy(selector.Columns(*ptgb.flds...)...)
if err := selector.Err(); err != nil {
return err
}
rows := &sql.Rows{}
query, args := selector.Query()
if err := ptgb.build.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}
// PasswordTokenSelect is the builder for selecting fields of PasswordToken entities.
type PasswordTokenSelect struct {
*PasswordTokenQuery
selector
}
// Aggregate adds the given aggregation functions to the selector query.
func (pts *PasswordTokenSelect) Aggregate(fns ...AggregateFunc) *PasswordTokenSelect {
pts.fns = append(pts.fns, fns...)
return pts
}
// Scan applies the selector query and scans the result into the given value.
func (pts *PasswordTokenSelect) Scan(ctx context.Context, v any) error {
ctx = setContextOp(ctx, pts.ctx, "Select")
if err := pts.prepareQuery(ctx); err != nil {
return err
}
return scanWithInterceptors[*PasswordTokenQuery, *PasswordTokenSelect](ctx, pts.PasswordTokenQuery, pts, pts.inters, v)
}
func (pts *PasswordTokenSelect) sqlScan(ctx context.Context, root *PasswordTokenQuery, v any) error {
selector := root.sqlQuery(ctx)
aggregation := make([]string, 0, len(pts.fns))
for _, fn := range pts.fns {
aggregation = append(aggregation, fn(selector))
}
switch n := len(*pts.selector.flds); {
case n == 0 && len(aggregation) > 0:
selector.Select(aggregation...)
case n != 0 && len(aggregation) > 0:
selector.AppendSelect(aggregation...)
}
rows := &sql.Rows{}
query, args := selector.Query()
if err := pts.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}

View File

@ -1,370 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"errors"
"fmt"
"time"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"git.grosinger.net/tgrosinger/saasitone/ent/passwordtoken"
"git.grosinger.net/tgrosinger/saasitone/ent/predicate"
"git.grosinger.net/tgrosinger/saasitone/ent/user"
)
// PasswordTokenUpdate is the builder for updating PasswordToken entities.
type PasswordTokenUpdate struct {
config
hooks []Hook
mutation *PasswordTokenMutation
}
// Where appends a list predicates to the PasswordTokenUpdate builder.
func (ptu *PasswordTokenUpdate) Where(ps ...predicate.PasswordToken) *PasswordTokenUpdate {
ptu.mutation.Where(ps...)
return ptu
}
// SetHash sets the "hash" field.
func (ptu *PasswordTokenUpdate) SetHash(s string) *PasswordTokenUpdate {
ptu.mutation.SetHash(s)
return ptu
}
// SetNillableHash sets the "hash" field if the given value is not nil.
func (ptu *PasswordTokenUpdate) SetNillableHash(s *string) *PasswordTokenUpdate {
if s != nil {
ptu.SetHash(*s)
}
return ptu
}
// SetCreatedAt sets the "created_at" field.
func (ptu *PasswordTokenUpdate) SetCreatedAt(t time.Time) *PasswordTokenUpdate {
ptu.mutation.SetCreatedAt(t)
return ptu
}
// SetNillableCreatedAt sets the "created_at" field if the given value is not nil.
func (ptu *PasswordTokenUpdate) SetNillableCreatedAt(t *time.Time) *PasswordTokenUpdate {
if t != nil {
ptu.SetCreatedAt(*t)
}
return ptu
}
// SetUserID sets the "user" edge to the User entity by ID.
func (ptu *PasswordTokenUpdate) SetUserID(id int) *PasswordTokenUpdate {
ptu.mutation.SetUserID(id)
return ptu
}
// SetUser sets the "user" edge to the User entity.
func (ptu *PasswordTokenUpdate) SetUser(u *User) *PasswordTokenUpdate {
return ptu.SetUserID(u.ID)
}
// Mutation returns the PasswordTokenMutation object of the builder.
func (ptu *PasswordTokenUpdate) Mutation() *PasswordTokenMutation {
return ptu.mutation
}
// ClearUser clears the "user" edge to the User entity.
func (ptu *PasswordTokenUpdate) ClearUser() *PasswordTokenUpdate {
ptu.mutation.ClearUser()
return ptu
}
// Save executes the query and returns the number of nodes affected by the update operation.
func (ptu *PasswordTokenUpdate) Save(ctx context.Context) (int, error) {
return withHooks(ctx, ptu.sqlSave, ptu.mutation, ptu.hooks)
}
// SaveX is like Save, but panics if an error occurs.
func (ptu *PasswordTokenUpdate) SaveX(ctx context.Context) int {
affected, err := ptu.Save(ctx)
if err != nil {
panic(err)
}
return affected
}
// Exec executes the query.
func (ptu *PasswordTokenUpdate) Exec(ctx context.Context) error {
_, err := ptu.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (ptu *PasswordTokenUpdate) ExecX(ctx context.Context) {
if err := ptu.Exec(ctx); err != nil {
panic(err)
}
}
// check runs all checks and user-defined validators on the builder.
func (ptu *PasswordTokenUpdate) check() error {
if v, ok := ptu.mutation.Hash(); ok {
if err := passwordtoken.HashValidator(v); err != nil {
return &ValidationError{Name: "hash", err: fmt.Errorf(`ent: validator failed for field "PasswordToken.hash": %w`, err)}
}
}
if _, ok := ptu.mutation.UserID(); ptu.mutation.UserCleared() && !ok {
return errors.New(`ent: clearing a required unique edge "PasswordToken.user"`)
}
return nil
}
func (ptu *PasswordTokenUpdate) sqlSave(ctx context.Context) (n int, err error) {
if err := ptu.check(); err != nil {
return n, err
}
_spec := sqlgraph.NewUpdateSpec(passwordtoken.Table, passwordtoken.Columns, sqlgraph.NewFieldSpec(passwordtoken.FieldID, field.TypeInt))
if ps := ptu.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if value, ok := ptu.mutation.Hash(); ok {
_spec.SetField(passwordtoken.FieldHash, field.TypeString, value)
}
if value, ok := ptu.mutation.CreatedAt(); ok {
_spec.SetField(passwordtoken.FieldCreatedAt, field.TypeTime, value)
}
if ptu.mutation.UserCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: passwordtoken.UserTable,
Columns: []string{passwordtoken.UserColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := ptu.mutation.UserIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: passwordtoken.UserTable,
Columns: []string{passwordtoken.UserColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if n, err = sqlgraph.UpdateNodes(ctx, ptu.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{passwordtoken.Label}
} else if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
return 0, err
}
ptu.mutation.done = true
return n, nil
}
// PasswordTokenUpdateOne is the builder for updating a single PasswordToken entity.
type PasswordTokenUpdateOne struct {
config
fields []string
hooks []Hook
mutation *PasswordTokenMutation
}
// SetHash sets the "hash" field.
func (ptuo *PasswordTokenUpdateOne) SetHash(s string) *PasswordTokenUpdateOne {
ptuo.mutation.SetHash(s)
return ptuo
}
// SetNillableHash sets the "hash" field if the given value is not nil.
func (ptuo *PasswordTokenUpdateOne) SetNillableHash(s *string) *PasswordTokenUpdateOne {
if s != nil {
ptuo.SetHash(*s)
}
return ptuo
}
// SetCreatedAt sets the "created_at" field.
func (ptuo *PasswordTokenUpdateOne) SetCreatedAt(t time.Time) *PasswordTokenUpdateOne {
ptuo.mutation.SetCreatedAt(t)
return ptuo
}
// SetNillableCreatedAt sets the "created_at" field if the given value is not nil.
func (ptuo *PasswordTokenUpdateOne) SetNillableCreatedAt(t *time.Time) *PasswordTokenUpdateOne {
if t != nil {
ptuo.SetCreatedAt(*t)
}
return ptuo
}
// SetUserID sets the "user" edge to the User entity by ID.
func (ptuo *PasswordTokenUpdateOne) SetUserID(id int) *PasswordTokenUpdateOne {
ptuo.mutation.SetUserID(id)
return ptuo
}
// SetUser sets the "user" edge to the User entity.
func (ptuo *PasswordTokenUpdateOne) SetUser(u *User) *PasswordTokenUpdateOne {
return ptuo.SetUserID(u.ID)
}
// Mutation returns the PasswordTokenMutation object of the builder.
func (ptuo *PasswordTokenUpdateOne) Mutation() *PasswordTokenMutation {
return ptuo.mutation
}
// ClearUser clears the "user" edge to the User entity.
func (ptuo *PasswordTokenUpdateOne) ClearUser() *PasswordTokenUpdateOne {
ptuo.mutation.ClearUser()
return ptuo
}
// Where appends a list predicates to the PasswordTokenUpdate builder.
func (ptuo *PasswordTokenUpdateOne) Where(ps ...predicate.PasswordToken) *PasswordTokenUpdateOne {
ptuo.mutation.Where(ps...)
return ptuo
}
// Select allows selecting one or more fields (columns) of the returned entity.
// The default is selecting all fields defined in the entity schema.
func (ptuo *PasswordTokenUpdateOne) Select(field string, fields ...string) *PasswordTokenUpdateOne {
ptuo.fields = append([]string{field}, fields...)
return ptuo
}
// Save executes the query and returns the updated PasswordToken entity.
func (ptuo *PasswordTokenUpdateOne) Save(ctx context.Context) (*PasswordToken, error) {
return withHooks(ctx, ptuo.sqlSave, ptuo.mutation, ptuo.hooks)
}
// SaveX is like Save, but panics if an error occurs.
func (ptuo *PasswordTokenUpdateOne) SaveX(ctx context.Context) *PasswordToken {
node, err := ptuo.Save(ctx)
if err != nil {
panic(err)
}
return node
}
// Exec executes the query on the entity.
func (ptuo *PasswordTokenUpdateOne) Exec(ctx context.Context) error {
_, err := ptuo.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (ptuo *PasswordTokenUpdateOne) ExecX(ctx context.Context) {
if err := ptuo.Exec(ctx); err != nil {
panic(err)
}
}
// check runs all checks and user-defined validators on the builder.
func (ptuo *PasswordTokenUpdateOne) check() error {
if v, ok := ptuo.mutation.Hash(); ok {
if err := passwordtoken.HashValidator(v); err != nil {
return &ValidationError{Name: "hash", err: fmt.Errorf(`ent: validator failed for field "PasswordToken.hash": %w`, err)}
}
}
if _, ok := ptuo.mutation.UserID(); ptuo.mutation.UserCleared() && !ok {
return errors.New(`ent: clearing a required unique edge "PasswordToken.user"`)
}
return nil
}
func (ptuo *PasswordTokenUpdateOne) sqlSave(ctx context.Context) (_node *PasswordToken, err error) {
if err := ptuo.check(); err != nil {
return _node, err
}
_spec := sqlgraph.NewUpdateSpec(passwordtoken.Table, passwordtoken.Columns, sqlgraph.NewFieldSpec(passwordtoken.FieldID, field.TypeInt))
id, ok := ptuo.mutation.ID()
if !ok {
return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "PasswordToken.id" for update`)}
}
_spec.Node.ID.Value = id
if fields := ptuo.fields; len(fields) > 0 {
_spec.Node.Columns = make([]string, 0, len(fields))
_spec.Node.Columns = append(_spec.Node.Columns, passwordtoken.FieldID)
for _, f := range fields {
if !passwordtoken.ValidColumn(f) {
return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
}
if f != passwordtoken.FieldID {
_spec.Node.Columns = append(_spec.Node.Columns, f)
}
}
}
if ps := ptuo.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if value, ok := ptuo.mutation.Hash(); ok {
_spec.SetField(passwordtoken.FieldHash, field.TypeString, value)
}
if value, ok := ptuo.mutation.CreatedAt(); ok {
_spec.SetField(passwordtoken.FieldCreatedAt, field.TypeTime, value)
}
if ptuo.mutation.UserCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: passwordtoken.UserTable,
Columns: []string{passwordtoken.UserColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := ptuo.mutation.UserIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: passwordtoken.UserTable,
Columns: []string{passwordtoken.UserColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
_node = &PasswordToken{config: ptuo.config}
_spec.Assign = _node.assignValues
_spec.ScanValues = _node.scanValues
if err = sqlgraph.UpdateNode(ctx, ptuo.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{passwordtoken.Label}
} else if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
return nil, err
}
ptuo.mutation.done = true
return _node, nil
}

View File

@ -1,13 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package predicate
import (
"entgo.io/ent/dialect/sql"
)
// PasswordToken is the predicate function for passwordtoken builders.
type PasswordToken func(*sql.Selector)
// User is the predicate function for user builders.
type User func(*sql.Selector)

View File

@ -1,5 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package ent
// The schema-stitching logic is generated in git.grosinger.net/tgrosinger/saasitone/ent/runtime/runtime.go

View File

@ -1,56 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package runtime
import (
"time"
"git.grosinger.net/tgrosinger/saasitone/ent/passwordtoken"
"git.grosinger.net/tgrosinger/saasitone/ent/schema"
"git.grosinger.net/tgrosinger/saasitone/ent/user"
)
// The init function reads all schema descriptors with runtime code
// (default values, validators, hooks and policies) and stitches it
// to their package variables.
func init() {
passwordtokenFields := schema.PasswordToken{}.Fields()
_ = passwordtokenFields
// passwordtokenDescHash is the schema descriptor for hash field.
passwordtokenDescHash := passwordtokenFields[0].Descriptor()
// passwordtoken.HashValidator is a validator for the "hash" field. It is called by the builders before save.
passwordtoken.HashValidator = passwordtokenDescHash.Validators[0].(func(string) error)
// passwordtokenDescCreatedAt is the schema descriptor for created_at field.
passwordtokenDescCreatedAt := passwordtokenFields[1].Descriptor()
// passwordtoken.DefaultCreatedAt holds the default value on creation for the created_at field.
passwordtoken.DefaultCreatedAt = passwordtokenDescCreatedAt.Default.(func() time.Time)
userHooks := schema.User{}.Hooks()
user.Hooks[0] = userHooks[0]
userFields := schema.User{}.Fields()
_ = userFields
// userDescName is the schema descriptor for name field.
userDescName := userFields[0].Descriptor()
// user.NameValidator is a validator for the "name" field. It is called by the builders before save.
user.NameValidator = userDescName.Validators[0].(func(string) error)
// userDescEmail is the schema descriptor for email field.
userDescEmail := userFields[1].Descriptor()
// user.EmailValidator is a validator for the "email" field. It is called by the builders before save.
user.EmailValidator = userDescEmail.Validators[0].(func(string) error)
// userDescPassword is the schema descriptor for password field.
userDescPassword := userFields[2].Descriptor()
// user.PasswordValidator is a validator for the "password" field. It is called by the builders before save.
user.PasswordValidator = userDescPassword.Validators[0].(func(string) error)
// userDescVerified is the schema descriptor for verified field.
userDescVerified := userFields[3].Descriptor()
// user.DefaultVerified holds the default value on creation for the verified field.
user.DefaultVerified = userDescVerified.Default.(bool)
// userDescCreatedAt is the schema descriptor for created_at field.
userDescCreatedAt := userFields[4].Descriptor()
// user.DefaultCreatedAt holds the default value on creation for the created_at field.
user.DefaultCreatedAt = userDescCreatedAt.Default.(func() time.Time)
}
const (
Version = "v0.12.5" // Version of ent codegen.
Sum = "h1:KREM5E4CSoej4zeGa88Ou/gfturAnpUv0mzAjch1sj4=" // Sum of ent codegen.
)

View File

@ -1,34 +0,0 @@
package schema
import (
"time"
"entgo.io/ent"
"entgo.io/ent/schema/edge"
"entgo.io/ent/schema/field"
)
// PasswordToken holds the schema definition for the PasswordToken entity.
type PasswordToken struct {
ent.Schema
}
// Fields of the PasswordToken.
func (PasswordToken) Fields() []ent.Field {
return []ent.Field{
field.String("hash").
Sensitive().
NotEmpty(),
field.Time("created_at").
Default(time.Now),
}
}
// Edges of the PasswordToken.
func (PasswordToken) Edges() []ent.Edge {
return []ent.Edge{
edge.To("user", User.Type).
Required().
Unique(),
}
}

View File

@ -1,64 +0,0 @@
package schema
import (
"context"
"strings"
"time"
"entgo.io/ent"
"entgo.io/ent/schema/edge"
"entgo.io/ent/schema/field"
ge "git.grosinger.net/tgrosinger/saasitone/ent"
"git.grosinger.net/tgrosinger/saasitone/ent/hook"
)
// User holds the schema definition for the User entity.
type User struct {
ent.Schema
}
// Fields of the User.
func (User) Fields() []ent.Field {
return []ent.Field{
field.String("name").
NotEmpty(),
field.String("email").
NotEmpty().
Unique(),
field.String("password").
Sensitive().
NotEmpty(),
field.Bool("verified").
Default(false),
field.Time("created_at").
Default(time.Now).
Immutable(),
}
}
// Edges of the User.
func (User) Edges() []ent.Edge {
return []ent.Edge{
edge.From("owner", PasswordToken.Type).
Ref("user"),
}
}
// Hooks of the User.
func (User) Hooks() []ent.Hook {
return []ent.Hook{
hook.On(
func(next ent.Mutator) ent.Mutator {
return hook.UserFunc(func(ctx context.Context, m *ge.UserMutation) (ent.Value, error) {
if v, exists := m.Email(); exists {
m.SetEmail(strings.ToLower(v))
}
return next.Mutate(ctx, m)
})
},
// Limit the hook only for these operations.
ent.OpCreate|ent.OpUpdate|ent.OpUpdateOne,
),
}
}

213
ent/tx.go
View File

@ -1,213 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"sync"
"entgo.io/ent/dialect"
)
// Tx is a transactional client that is created by calling Client.Tx().
type Tx struct {
config
// PasswordToken is the client for interacting with the PasswordToken builders.
PasswordToken *PasswordTokenClient
// User is the client for interacting with the User builders.
User *UserClient
// lazily loaded.
client *Client
clientOnce sync.Once
// ctx lives for the life of the transaction. It is
// the same context used by the underlying connection.
ctx context.Context
}
type (
// Committer is the interface that wraps the Commit method.
Committer interface {
Commit(context.Context, *Tx) error
}
// The CommitFunc type is an adapter to allow the use of ordinary
// function as a Committer. If f is a function with the appropriate
// signature, CommitFunc(f) is a Committer that calls f.
CommitFunc func(context.Context, *Tx) error
// CommitHook defines the "commit middleware". A function that gets a Committer
// and returns a Committer. For example:
//
// hook := func(next ent.Committer) ent.Committer {
// return ent.CommitFunc(func(ctx context.Context, tx *ent.Tx) error {
// // Do some stuff before.
// if err := next.Commit(ctx, tx); err != nil {
// return err
// }
// // Do some stuff after.
// return nil
// })
// }
//
CommitHook func(Committer) Committer
)
// Commit calls f(ctx, m).
func (f CommitFunc) Commit(ctx context.Context, tx *Tx) error {
return f(ctx, tx)
}
// Commit commits the transaction.
func (tx *Tx) Commit() error {
txDriver := tx.config.driver.(*txDriver)
var fn Committer = CommitFunc(func(context.Context, *Tx) error {
return txDriver.tx.Commit()
})
txDriver.mu.Lock()
hooks := append([]CommitHook(nil), txDriver.onCommit...)
txDriver.mu.Unlock()
for i := len(hooks) - 1; i >= 0; i-- {
fn = hooks[i](fn)
}
return fn.Commit(tx.ctx, tx)
}
// OnCommit adds a hook to call on commit.
func (tx *Tx) OnCommit(f CommitHook) {
txDriver := tx.config.driver.(*txDriver)
txDriver.mu.Lock()
txDriver.onCommit = append(txDriver.onCommit, f)
txDriver.mu.Unlock()
}
type (
// Rollbacker is the interface that wraps the Rollback method.
Rollbacker interface {
Rollback(context.Context, *Tx) error
}
// The RollbackFunc type is an adapter to allow the use of ordinary
// function as a Rollbacker. If f is a function with the appropriate
// signature, RollbackFunc(f) is a Rollbacker that calls f.
RollbackFunc func(context.Context, *Tx) error
// RollbackHook defines the "rollback middleware". A function that gets a Rollbacker
// and returns a Rollbacker. For example:
//
// hook := func(next ent.Rollbacker) ent.Rollbacker {
// return ent.RollbackFunc(func(ctx context.Context, tx *ent.Tx) error {
// // Do some stuff before.
// if err := next.Rollback(ctx, tx); err != nil {
// return err
// }
// // Do some stuff after.
// return nil
// })
// }
//
RollbackHook func(Rollbacker) Rollbacker
)
// Rollback calls f(ctx, m).
func (f RollbackFunc) Rollback(ctx context.Context, tx *Tx) error {
return f(ctx, tx)
}
// Rollback rollbacks the transaction.
func (tx *Tx) Rollback() error {
txDriver := tx.config.driver.(*txDriver)
var fn Rollbacker = RollbackFunc(func(context.Context, *Tx) error {
return txDriver.tx.Rollback()
})
txDriver.mu.Lock()
hooks := append([]RollbackHook(nil), txDriver.onRollback...)
txDriver.mu.Unlock()
for i := len(hooks) - 1; i >= 0; i-- {
fn = hooks[i](fn)
}
return fn.Rollback(tx.ctx, tx)
}
// OnRollback adds a hook to call on rollback.
func (tx *Tx) OnRollback(f RollbackHook) {
txDriver := tx.config.driver.(*txDriver)
txDriver.mu.Lock()
txDriver.onRollback = append(txDriver.onRollback, f)
txDriver.mu.Unlock()
}
// Client returns a Client that binds to current transaction.
func (tx *Tx) Client() *Client {
tx.clientOnce.Do(func() {
tx.client = &Client{config: tx.config}
tx.client.init()
})
return tx.client
}
func (tx *Tx) init() {
tx.PasswordToken = NewPasswordTokenClient(tx.config)
tx.User = NewUserClient(tx.config)
}
// txDriver wraps the given dialect.Tx with a nop dialect.Driver implementation.
// The idea is to support transactions without adding any extra code to the builders.
// When a builder calls to driver.Tx(), it gets the same dialect.Tx instance.
// Commit and Rollback are nop for the internal builders and the user must call one
// of them in order to commit or rollback the transaction.
//
// If a closed transaction is embedded in one of the generated entities, and the entity
// applies a query, for example: PasswordToken.QueryXXX(), the query will be executed
// through the driver which created this transaction.
//
// Note that txDriver is not goroutine safe.
type txDriver struct {
// the driver we started the transaction from.
drv dialect.Driver
// tx is the underlying transaction.
tx dialect.Tx
// completion hooks.
mu sync.Mutex
onCommit []CommitHook
onRollback []RollbackHook
}
// newTx creates a new transactional driver.
func newTx(ctx context.Context, drv dialect.Driver) (*txDriver, error) {
tx, err := drv.Tx(ctx)
if err != nil {
return nil, err
}
return &txDriver{tx: tx, drv: drv}, nil
}
// Tx returns the transaction wrapper (txDriver) to avoid Commit or Rollback calls
// from the internal builders. Should be called only by the internal builders.
func (tx *txDriver) Tx(context.Context) (dialect.Tx, error) { return tx, nil }
// Dialect returns the dialect of the driver we started the transaction from.
func (tx *txDriver) Dialect() string { return tx.drv.Dialect() }
// Close is a nop close.
func (*txDriver) Close() error { return nil }
// Commit is a nop commit for the internal builders.
// User must call `Tx.Commit` in order to commit the transaction.
func (*txDriver) Commit() error { return nil }
// Rollback is a nop rollback for the internal builders.
// User must call `Tx.Rollback` in order to rollback the transaction.
func (*txDriver) Rollback() error { return nil }
// Exec calls tx.Exec.
func (tx *txDriver) Exec(ctx context.Context, query string, args, v any) error {
return tx.tx.Exec(ctx, query, args, v)
}
// Query calls tx.Query.
func (tx *txDriver) Query(ctx context.Context, query string, args, v any) error {
return tx.tx.Query(ctx, query, args, v)
}
var _ dialect.Driver = (*txDriver)(nil)

View File

@ -1,178 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"fmt"
"strings"
"time"
"entgo.io/ent"
"entgo.io/ent/dialect/sql"
"git.grosinger.net/tgrosinger/saasitone/ent/user"
)
// User is the model entity for the User schema.
type User struct {
config `json:"-"`
// ID of the ent.
ID int `json:"id,omitempty"`
// Name holds the value of the "name" field.
Name string `json:"name,omitempty"`
// Email holds the value of the "email" field.
Email string `json:"email,omitempty"`
// Password holds the value of the "password" field.
Password string `json:"-"`
// Verified holds the value of the "verified" field.
Verified bool `json:"verified,omitempty"`
// CreatedAt holds the value of the "created_at" field.
CreatedAt time.Time `json:"created_at,omitempty"`
// Edges holds the relations/edges for other nodes in the graph.
// The values are being populated by the UserQuery when eager-loading is set.
Edges UserEdges `json:"edges"`
selectValues sql.SelectValues
}
// UserEdges holds the relations/edges for other nodes in the graph.
type UserEdges struct {
// Owner holds the value of the owner edge.
Owner []*PasswordToken `json:"owner,omitempty"`
// loadedTypes holds the information for reporting if a
// type was loaded (or requested) in eager-loading or not.
loadedTypes [1]bool
}
// OwnerOrErr returns the Owner value or an error if the edge
// was not loaded in eager-loading.
func (e UserEdges) OwnerOrErr() ([]*PasswordToken, error) {
if e.loadedTypes[0] {
return e.Owner, nil
}
return nil, &NotLoadedError{edge: "owner"}
}
// scanValues returns the types for scanning values from sql.Rows.
func (*User) scanValues(columns []string) ([]any, error) {
values := make([]any, len(columns))
for i := range columns {
switch columns[i] {
case user.FieldVerified:
values[i] = new(sql.NullBool)
case user.FieldID:
values[i] = new(sql.NullInt64)
case user.FieldName, user.FieldEmail, user.FieldPassword:
values[i] = new(sql.NullString)
case user.FieldCreatedAt:
values[i] = new(sql.NullTime)
default:
values[i] = new(sql.UnknownType)
}
}
return values, nil
}
// assignValues assigns the values that were returned from sql.Rows (after scanning)
// to the User fields.
func (u *User) assignValues(columns []string, values []any) error {
if m, n := len(values), len(columns); m < n {
return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
}
for i := range columns {
switch columns[i] {
case user.FieldID:
value, ok := values[i].(*sql.NullInt64)
if !ok {
return fmt.Errorf("unexpected type %T for field id", value)
}
u.ID = int(value.Int64)
case user.FieldName:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field name", values[i])
} else if value.Valid {
u.Name = value.String
}
case user.FieldEmail:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field email", values[i])
} else if value.Valid {
u.Email = value.String
}
case user.FieldPassword:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field password", values[i])
} else if value.Valid {
u.Password = value.String
}
case user.FieldVerified:
if value, ok := values[i].(*sql.NullBool); !ok {
return fmt.Errorf("unexpected type %T for field verified", values[i])
} else if value.Valid {
u.Verified = value.Bool
}
case user.FieldCreatedAt:
if value, ok := values[i].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field created_at", values[i])
} else if value.Valid {
u.CreatedAt = value.Time
}
default:
u.selectValues.Set(columns[i], values[i])
}
}
return nil
}
// Value returns the ent.Value that was dynamically selected and assigned to the User.
// This includes values selected through modifiers, order, etc.
func (u *User) Value(name string) (ent.Value, error) {
return u.selectValues.Get(name)
}
// QueryOwner queries the "owner" edge of the User entity.
func (u *User) QueryOwner() *PasswordTokenQuery {
return NewUserClient(u.config).QueryOwner(u)
}
// Update returns a builder for updating this User.
// Note that you need to call User.Unwrap() before calling this method if this User
// was returned from a transaction, and the transaction was committed or rolled back.
func (u *User) Update() *UserUpdateOne {
return NewUserClient(u.config).UpdateOne(u)
}
// Unwrap unwraps the User entity that was returned from a transaction after it was closed,
// so that all future queries will be executed through the driver which created the transaction.
func (u *User) Unwrap() *User {
_tx, ok := u.config.driver.(*txDriver)
if !ok {
panic("ent: User is not a transactional entity")
}
u.config.driver = _tx.drv
return u
}
// String implements the fmt.Stringer.
func (u *User) String() string {
var builder strings.Builder
builder.WriteString("User(")
builder.WriteString(fmt.Sprintf("id=%v, ", u.ID))
builder.WriteString("name=")
builder.WriteString(u.Name)
builder.WriteString(", ")
builder.WriteString("email=")
builder.WriteString(u.Email)
builder.WriteString(", ")
builder.WriteString("password=<sensitive>")
builder.WriteString(", ")
builder.WriteString("verified=")
builder.WriteString(fmt.Sprintf("%v", u.Verified))
builder.WriteString(", ")
builder.WriteString("created_at=")
builder.WriteString(u.CreatedAt.Format(time.ANSIC))
builder.WriteByte(')')
return builder.String()
}
// Users is a parsable slice of User.
type Users []*User

View File

@ -1,133 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package user
import (
"time"
"entgo.io/ent"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
)
const (
// Label holds the string label denoting the user type in the database.
Label = "user"
// FieldID holds the string denoting the id field in the database.
FieldID = "id"
// FieldName holds the string denoting the name field in the database.
FieldName = "name"
// FieldEmail holds the string denoting the email field in the database.
FieldEmail = "email"
// FieldPassword holds the string denoting the password field in the database.
FieldPassword = "password"
// FieldVerified holds the string denoting the verified field in the database.
FieldVerified = "verified"
// FieldCreatedAt holds the string denoting the created_at field in the database.
FieldCreatedAt = "created_at"
// EdgeOwner holds the string denoting the owner edge name in mutations.
EdgeOwner = "owner"
// Table holds the table name of the user in the database.
Table = "users"
// OwnerTable is the table that holds the owner relation/edge.
OwnerTable = "password_tokens"
// OwnerInverseTable is the table name for the PasswordToken entity.
// It exists in this package in order to avoid circular dependency with the "passwordtoken" package.
OwnerInverseTable = "password_tokens"
// OwnerColumn is the table column denoting the owner relation/edge.
OwnerColumn = "password_token_user"
)
// Columns holds all SQL columns for user fields.
var Columns = []string{
FieldID,
FieldName,
FieldEmail,
FieldPassword,
FieldVerified,
FieldCreatedAt,
}
// ValidColumn reports if the column name is valid (part of the table columns).
func ValidColumn(column string) bool {
for i := range Columns {
if column == Columns[i] {
return true
}
}
return false
}
// Note that the variables below are initialized by the runtime
// package on the initialization of the application. Therefore,
// it should be imported in the main as follows:
//
// import _ "git.grosinger.net/tgrosinger/saasitone/ent/runtime"
var (
Hooks [1]ent.Hook
// NameValidator is a validator for the "name" field. It is called by the builders before save.
NameValidator func(string) error
// EmailValidator is a validator for the "email" field. It is called by the builders before save.
EmailValidator func(string) error
// PasswordValidator is a validator for the "password" field. It is called by the builders before save.
PasswordValidator func(string) error
// DefaultVerified holds the default value on creation for the "verified" field.
DefaultVerified bool
// DefaultCreatedAt holds the default value on creation for the "created_at" field.
DefaultCreatedAt func() time.Time
)
// OrderOption defines the ordering options for the User queries.
type OrderOption func(*sql.Selector)
// ByID orders the results by the id field.
func ByID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldID, opts...).ToFunc()
}
// ByName orders the results by the name field.
func ByName(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldName, opts...).ToFunc()
}
// ByEmail orders the results by the email field.
func ByEmail(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldEmail, opts...).ToFunc()
}
// ByPassword orders the results by the password field.
func ByPassword(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldPassword, opts...).ToFunc()
}
// ByVerified orders the results by the verified field.
func ByVerified(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldVerified, opts...).ToFunc()
}
// ByCreatedAt orders the results by the created_at field.
func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldCreatedAt, opts...).ToFunc()
}
// ByOwnerCount orders the results by owner count.
func ByOwnerCount(opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborsCount(s, newOwnerStep(), opts...)
}
}
// ByOwner orders the results by owner terms.
func ByOwner(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newOwnerStep(), append([]sql.OrderTerm{term}, terms...)...)
}
}
func newOwnerStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(OwnerInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.O2M, true, OwnerTable, OwnerColumn),
)
}

View File

@ -1,365 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package user
import (
"time"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"git.grosinger.net/tgrosinger/saasitone/ent/predicate"
)
// ID filters vertices based on their ID field.
func ID(id int) predicate.User {
return predicate.User(sql.FieldEQ(FieldID, id))
}
// IDEQ applies the EQ predicate on the ID field.
func IDEQ(id int) predicate.User {
return predicate.User(sql.FieldEQ(FieldID, id))
}
// IDNEQ applies the NEQ predicate on the ID field.
func IDNEQ(id int) predicate.User {
return predicate.User(sql.FieldNEQ(FieldID, id))
}
// IDIn applies the In predicate on the ID field.
func IDIn(ids ...int) predicate.User {
return predicate.User(sql.FieldIn(FieldID, ids...))
}
// IDNotIn applies the NotIn predicate on the ID field.
func IDNotIn(ids ...int) predicate.User {
return predicate.User(sql.FieldNotIn(FieldID, ids...))
}
// IDGT applies the GT predicate on the ID field.
func IDGT(id int) predicate.User {
return predicate.User(sql.FieldGT(FieldID, id))
}
// IDGTE applies the GTE predicate on the ID field.
func IDGTE(id int) predicate.User {
return predicate.User(sql.FieldGTE(FieldID, id))
}
// IDLT applies the LT predicate on the ID field.
func IDLT(id int) predicate.User {
return predicate.User(sql.FieldLT(FieldID, id))
}
// IDLTE applies the LTE predicate on the ID field.
func IDLTE(id int) predicate.User {
return predicate.User(sql.FieldLTE(FieldID, id))
}
// Name applies equality check predicate on the "name" field. It's identical to NameEQ.
func Name(v string) predicate.User {
return predicate.User(sql.FieldEQ(FieldName, v))
}
// Email applies equality check predicate on the "email" field. It's identical to EmailEQ.
func Email(v string) predicate.User {
return predicate.User(sql.FieldEQ(FieldEmail, v))
}
// Password applies equality check predicate on the "password" field. It's identical to PasswordEQ.
func Password(v string) predicate.User {
return predicate.User(sql.FieldEQ(FieldPassword, v))
}
// Verified applies equality check predicate on the "verified" field. It's identical to VerifiedEQ.
func Verified(v bool) predicate.User {
return predicate.User(sql.FieldEQ(FieldVerified, v))
}
// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
func CreatedAt(v time.Time) predicate.User {
return predicate.User(sql.FieldEQ(FieldCreatedAt, v))
}
// NameEQ applies the EQ predicate on the "name" field.
func NameEQ(v string) predicate.User {
return predicate.User(sql.FieldEQ(FieldName, v))
}
// NameNEQ applies the NEQ predicate on the "name" field.
func NameNEQ(v string) predicate.User {
return predicate.User(sql.FieldNEQ(FieldName, v))
}
// NameIn applies the In predicate on the "name" field.
func NameIn(vs ...string) predicate.User {
return predicate.User(sql.FieldIn(FieldName, vs...))
}
// NameNotIn applies the NotIn predicate on the "name" field.
func NameNotIn(vs ...string) predicate.User {
return predicate.User(sql.FieldNotIn(FieldName, vs...))
}
// NameGT applies the GT predicate on the "name" field.
func NameGT(v string) predicate.User {
return predicate.User(sql.FieldGT(FieldName, v))
}
// NameGTE applies the GTE predicate on the "name" field.
func NameGTE(v string) predicate.User {
return predicate.User(sql.FieldGTE(FieldName, v))
}
// NameLT applies the LT predicate on the "name" field.
func NameLT(v string) predicate.User {
return predicate.User(sql.FieldLT(FieldName, v))
}
// NameLTE applies the LTE predicate on the "name" field.
func NameLTE(v string) predicate.User {
return predicate.User(sql.FieldLTE(FieldName, v))
}
// NameContains applies the Contains predicate on the "name" field.
func NameContains(v string) predicate.User {
return predicate.User(sql.FieldContains(FieldName, v))
}
// NameHasPrefix applies the HasPrefix predicate on the "name" field.
func NameHasPrefix(v string) predicate.User {
return predicate.User(sql.FieldHasPrefix(FieldName, v))
}
// NameHasSuffix applies the HasSuffix predicate on the "name" field.
func NameHasSuffix(v string) predicate.User {
return predicate.User(sql.FieldHasSuffix(FieldName, v))
}
// NameEqualFold applies the EqualFold predicate on the "name" field.
func NameEqualFold(v string) predicate.User {
return predicate.User(sql.FieldEqualFold(FieldName, v))
}
// NameContainsFold applies the ContainsFold predicate on the "name" field.
func NameContainsFold(v string) predicate.User {
return predicate.User(sql.FieldContainsFold(FieldName, v))
}
// EmailEQ applies the EQ predicate on the "email" field.
func EmailEQ(v string) predicate.User {
return predicate.User(sql.FieldEQ(FieldEmail, v))
}
// EmailNEQ applies the NEQ predicate on the "email" field.
func EmailNEQ(v string) predicate.User {
return predicate.User(sql.FieldNEQ(FieldEmail, v))
}
// EmailIn applies the In predicate on the "email" field.
func EmailIn(vs ...string) predicate.User {
return predicate.User(sql.FieldIn(FieldEmail, vs...))
}
// EmailNotIn applies the NotIn predicate on the "email" field.
func EmailNotIn(vs ...string) predicate.User {
return predicate.User(sql.FieldNotIn(FieldEmail, vs...))
}
// EmailGT applies the GT predicate on the "email" field.
func EmailGT(v string) predicate.User {
return predicate.User(sql.FieldGT(FieldEmail, v))
}
// EmailGTE applies the GTE predicate on the "email" field.
func EmailGTE(v string) predicate.User {
return predicate.User(sql.FieldGTE(FieldEmail, v))
}
// EmailLT applies the LT predicate on the "email" field.
func EmailLT(v string) predicate.User {
return predicate.User(sql.FieldLT(FieldEmail, v))
}
// EmailLTE applies the LTE predicate on the "email" field.
func EmailLTE(v string) predicate.User {
return predicate.User(sql.FieldLTE(FieldEmail, v))
}
// EmailContains applies the Contains predicate on the "email" field.
func EmailContains(v string) predicate.User {
return predicate.User(sql.FieldContains(FieldEmail, v))
}
// EmailHasPrefix applies the HasPrefix predicate on the "email" field.
func EmailHasPrefix(v string) predicate.User {
return predicate.User(sql.FieldHasPrefix(FieldEmail, v))
}
// EmailHasSuffix applies the HasSuffix predicate on the "email" field.
func EmailHasSuffix(v string) predicate.User {
return predicate.User(sql.FieldHasSuffix(FieldEmail, v))
}
// EmailEqualFold applies the EqualFold predicate on the "email" field.
func EmailEqualFold(v string) predicate.User {
return predicate.User(sql.FieldEqualFold(FieldEmail, v))
}
// EmailContainsFold applies the ContainsFold predicate on the "email" field.
func EmailContainsFold(v string) predicate.User {
return predicate.User(sql.FieldContainsFold(FieldEmail, v))
}
// PasswordEQ applies the EQ predicate on the "password" field.
func PasswordEQ(v string) predicate.User {
return predicate.User(sql.FieldEQ(FieldPassword, v))
}
// PasswordNEQ applies the NEQ predicate on the "password" field.
func PasswordNEQ(v string) predicate.User {
return predicate.User(sql.FieldNEQ(FieldPassword, v))
}
// PasswordIn applies the In predicate on the "password" field.
func PasswordIn(vs ...string) predicate.User {
return predicate.User(sql.FieldIn(FieldPassword, vs...))
}
// PasswordNotIn applies the NotIn predicate on the "password" field.
func PasswordNotIn(vs ...string) predicate.User {
return predicate.User(sql.FieldNotIn(FieldPassword, vs...))
}
// PasswordGT applies the GT predicate on the "password" field.
func PasswordGT(v string) predicate.User {
return predicate.User(sql.FieldGT(FieldPassword, v))
}
// PasswordGTE applies the GTE predicate on the "password" field.
func PasswordGTE(v string) predicate.User {
return predicate.User(sql.FieldGTE(FieldPassword, v))
}
// PasswordLT applies the LT predicate on the "password" field.
func PasswordLT(v string) predicate.User {
return predicate.User(sql.FieldLT(FieldPassword, v))
}
// PasswordLTE applies the LTE predicate on the "password" field.
func PasswordLTE(v string) predicate.User {
return predicate.User(sql.FieldLTE(FieldPassword, v))
}
// PasswordContains applies the Contains predicate on the "password" field.
func PasswordContains(v string) predicate.User {
return predicate.User(sql.FieldContains(FieldPassword, v))
}
// PasswordHasPrefix applies the HasPrefix predicate on the "password" field.
func PasswordHasPrefix(v string) predicate.User {
return predicate.User(sql.FieldHasPrefix(FieldPassword, v))
}
// PasswordHasSuffix applies the HasSuffix predicate on the "password" field.
func PasswordHasSuffix(v string) predicate.User {
return predicate.User(sql.FieldHasSuffix(FieldPassword, v))
}
// PasswordEqualFold applies the EqualFold predicate on the "password" field.
func PasswordEqualFold(v string) predicate.User {
return predicate.User(sql.FieldEqualFold(FieldPassword, v))
}
// PasswordContainsFold applies the ContainsFold predicate on the "password" field.
func PasswordContainsFold(v string) predicate.User {
return predicate.User(sql.FieldContainsFold(FieldPassword, v))
}
// VerifiedEQ applies the EQ predicate on the "verified" field.
func VerifiedEQ(v bool) predicate.User {
return predicate.User(sql.FieldEQ(FieldVerified, v))
}
// VerifiedNEQ applies the NEQ predicate on the "verified" field.
func VerifiedNEQ(v bool) predicate.User {
return predicate.User(sql.FieldNEQ(FieldVerified, v))
}
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
func CreatedAtEQ(v time.Time) predicate.User {
return predicate.User(sql.FieldEQ(FieldCreatedAt, v))
}
// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
func CreatedAtNEQ(v time.Time) predicate.User {
return predicate.User(sql.FieldNEQ(FieldCreatedAt, v))
}
// CreatedAtIn applies the In predicate on the "created_at" field.
func CreatedAtIn(vs ...time.Time) predicate.User {
return predicate.User(sql.FieldIn(FieldCreatedAt, vs...))
}
// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
func CreatedAtNotIn(vs ...time.Time) predicate.User {
return predicate.User(sql.FieldNotIn(FieldCreatedAt, vs...))
}
// CreatedAtGT applies the GT predicate on the "created_at" field.
func CreatedAtGT(v time.Time) predicate.User {
return predicate.User(sql.FieldGT(FieldCreatedAt, v))
}
// CreatedAtGTE applies the GTE predicate on the "created_at" field.
func CreatedAtGTE(v time.Time) predicate.User {
return predicate.User(sql.FieldGTE(FieldCreatedAt, v))
}
// CreatedAtLT applies the LT predicate on the "created_at" field.
func CreatedAtLT(v time.Time) predicate.User {
return predicate.User(sql.FieldLT(FieldCreatedAt, v))
}
// CreatedAtLTE applies the LTE predicate on the "created_at" field.
func CreatedAtLTE(v time.Time) predicate.User {
return predicate.User(sql.FieldLTE(FieldCreatedAt, v))
}
// HasOwner applies the HasEdge predicate on the "owner" edge.
func HasOwner() predicate.User {
return predicate.User(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.O2M, true, OwnerTable, OwnerColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasOwnerWith applies the HasEdge predicate on the "owner" edge with a given conditions (other predicates).
func HasOwnerWith(preds ...predicate.PasswordToken) predicate.User {
return predicate.User(func(s *sql.Selector) {
step := newOwnerStep()
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
p(s)
}
})
})
}
// And groups predicates with the AND operator between them.
func And(predicates ...predicate.User) predicate.User {
return predicate.User(sql.AndPredicates(predicates...))
}
// Or groups predicates with the OR operator between them.
func Or(predicates ...predicate.User) predicate.User {
return predicate.User(sql.OrPredicates(predicates...))
}
// Not applies the not operator on the given predicate.
func Not(p predicate.User) predicate.User {
return predicate.User(sql.NotPredicates(p))
}

View File

@ -1,320 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"errors"
"fmt"
"time"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"git.grosinger.net/tgrosinger/saasitone/ent/passwordtoken"
"git.grosinger.net/tgrosinger/saasitone/ent/user"
)
// UserCreate is the builder for creating a User entity.
type UserCreate struct {
config
mutation *UserMutation
hooks []Hook
}
// SetName sets the "name" field.
func (uc *UserCreate) SetName(s string) *UserCreate {
uc.mutation.SetName(s)
return uc
}
// SetEmail sets the "email" field.
func (uc *UserCreate) SetEmail(s string) *UserCreate {
uc.mutation.SetEmail(s)
return uc
}
// SetPassword sets the "password" field.
func (uc *UserCreate) SetPassword(s string) *UserCreate {
uc.mutation.SetPassword(s)
return uc
}
// SetVerified sets the "verified" field.
func (uc *UserCreate) SetVerified(b bool) *UserCreate {
uc.mutation.SetVerified(b)
return uc
}
// SetNillableVerified sets the "verified" field if the given value is not nil.
func (uc *UserCreate) SetNillableVerified(b *bool) *UserCreate {
if b != nil {
uc.SetVerified(*b)
}
return uc
}
// SetCreatedAt sets the "created_at" field.
func (uc *UserCreate) SetCreatedAt(t time.Time) *UserCreate {
uc.mutation.SetCreatedAt(t)
return uc
}
// SetNillableCreatedAt sets the "created_at" field if the given value is not nil.
func (uc *UserCreate) SetNillableCreatedAt(t *time.Time) *UserCreate {
if t != nil {
uc.SetCreatedAt(*t)
}
return uc
}
// AddOwnerIDs adds the "owner" edge to the PasswordToken entity by IDs.
func (uc *UserCreate) AddOwnerIDs(ids ...int) *UserCreate {
uc.mutation.AddOwnerIDs(ids...)
return uc
}
// AddOwner adds the "owner" edges to the PasswordToken entity.
func (uc *UserCreate) AddOwner(p ...*PasswordToken) *UserCreate {
ids := make([]int, len(p))
for i := range p {
ids[i] = p[i].ID
}
return uc.AddOwnerIDs(ids...)
}
// Mutation returns the UserMutation object of the builder.
func (uc *UserCreate) Mutation() *UserMutation {
return uc.mutation
}
// Save creates the User in the database.
func (uc *UserCreate) Save(ctx context.Context) (*User, error) {
if err := uc.defaults(); err != nil {
return nil, err
}
return withHooks(ctx, uc.sqlSave, uc.mutation, uc.hooks)
}
// SaveX calls Save and panics if Save returns an error.
func (uc *UserCreate) SaveX(ctx context.Context) *User {
v, err := uc.Save(ctx)
if err != nil {
panic(err)
}
return v
}
// Exec executes the query.
func (uc *UserCreate) Exec(ctx context.Context) error {
_, err := uc.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (uc *UserCreate) ExecX(ctx context.Context) {
if err := uc.Exec(ctx); err != nil {
panic(err)
}
}
// defaults sets the default values of the builder before save.
func (uc *UserCreate) defaults() error {
if _, ok := uc.mutation.Verified(); !ok {
v := user.DefaultVerified
uc.mutation.SetVerified(v)
}
if _, ok := uc.mutation.CreatedAt(); !ok {
if user.DefaultCreatedAt == nil {
return fmt.Errorf("ent: uninitialized user.DefaultCreatedAt (forgotten import ent/runtime?)")
}
v := user.DefaultCreatedAt()
uc.mutation.SetCreatedAt(v)
}
return nil
}
// check runs all checks and user-defined validators on the builder.
func (uc *UserCreate) check() error {
if _, ok := uc.mutation.Name(); !ok {
return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "User.name"`)}
}
if v, ok := uc.mutation.Name(); ok {
if err := user.NameValidator(v); err != nil {
return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "User.name": %w`, err)}
}
}
if _, ok := uc.mutation.Email(); !ok {
return &ValidationError{Name: "email", err: errors.New(`ent: missing required field "User.email"`)}
}
if v, ok := uc.mutation.Email(); ok {
if err := user.EmailValidator(v); err != nil {
return &ValidationError{Name: "email", err: fmt.Errorf(`ent: validator failed for field "User.email": %w`, err)}
}
}
if _, ok := uc.mutation.Password(); !ok {
return &ValidationError{Name: "password", err: errors.New(`ent: missing required field "User.password"`)}
}
if v, ok := uc.mutation.Password(); ok {
if err := user.PasswordValidator(v); err != nil {
return &ValidationError{Name: "password", err: fmt.Errorf(`ent: validator failed for field "User.password": %w`, err)}
}
}
if _, ok := uc.mutation.Verified(); !ok {
return &ValidationError{Name: "verified", err: errors.New(`ent: missing required field "User.verified"`)}
}
if _, ok := uc.mutation.CreatedAt(); !ok {
return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "User.created_at"`)}
}
return nil
}
func (uc *UserCreate) sqlSave(ctx context.Context) (*User, error) {
if err := uc.check(); err != nil {
return nil, err
}
_node, _spec := uc.createSpec()
if err := sqlgraph.CreateNode(ctx, uc.driver, _spec); err != nil {
if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
return nil, err
}
id := _spec.ID.Value.(int64)
_node.ID = int(id)
uc.mutation.id = &_node.ID
uc.mutation.done = true
return _node, nil
}
func (uc *UserCreate) createSpec() (*User, *sqlgraph.CreateSpec) {
var (
_node = &User{config: uc.config}
_spec = sqlgraph.NewCreateSpec(user.Table, sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt))
)
if value, ok := uc.mutation.Name(); ok {
_spec.SetField(user.FieldName, field.TypeString, value)
_node.Name = value
}
if value, ok := uc.mutation.Email(); ok {
_spec.SetField(user.FieldEmail, field.TypeString, value)
_node.Email = value
}
if value, ok := uc.mutation.Password(); ok {
_spec.SetField(user.FieldPassword, field.TypeString, value)
_node.Password = value
}
if value, ok := uc.mutation.Verified(); ok {
_spec.SetField(user.FieldVerified, field.TypeBool, value)
_node.Verified = value
}
if value, ok := uc.mutation.CreatedAt(); ok {
_spec.SetField(user.FieldCreatedAt, field.TypeTime, value)
_node.CreatedAt = value
}
if nodes := uc.mutation.OwnerIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: user.OwnerTable,
Columns: []string{user.OwnerColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(passwordtoken.FieldID, field.TypeInt),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges = append(_spec.Edges, edge)
}
return _node, _spec
}
// UserCreateBulk is the builder for creating many User entities in bulk.
type UserCreateBulk struct {
config
err error
builders []*UserCreate
}
// Save creates the User entities in the database.
func (ucb *UserCreateBulk) Save(ctx context.Context) ([]*User, error) {
if ucb.err != nil {
return nil, ucb.err
}
specs := make([]*sqlgraph.CreateSpec, len(ucb.builders))
nodes := make([]*User, len(ucb.builders))
mutators := make([]Mutator, len(ucb.builders))
for i := range ucb.builders {
func(i int, root context.Context) {
builder := ucb.builders[i]
builder.defaults()
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
mutation, ok := m.(*UserMutation)
if !ok {
return nil, fmt.Errorf("unexpected mutation type %T", m)
}
if err := builder.check(); err != nil {
return nil, err
}
builder.mutation = mutation
var err error
nodes[i], specs[i] = builder.createSpec()
if i < len(mutators)-1 {
_, err = mutators[i+1].Mutate(root, ucb.builders[i+1].mutation)
} else {
spec := &sqlgraph.BatchCreateSpec{Nodes: specs}
// Invoke the actual operation on the latest mutation in the chain.
if err = sqlgraph.BatchCreate(ctx, ucb.driver, spec); err != nil {
if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
}
}
if err != nil {
return nil, err
}
mutation.id = &nodes[i].ID
if specs[i].ID.Value != nil {
id := specs[i].ID.Value.(int64)
nodes[i].ID = int(id)
}
mutation.done = true
return nodes[i], nil
})
for i := len(builder.hooks) - 1; i >= 0; i-- {
mut = builder.hooks[i](mut)
}
mutators[i] = mut
}(i, ctx)
}
if len(mutators) > 0 {
if _, err := mutators[0].Mutate(ctx, ucb.builders[0].mutation); err != nil {
return nil, err
}
}
return nodes, nil
}
// SaveX is like Save, but panics if an error occurs.
func (ucb *UserCreateBulk) SaveX(ctx context.Context) []*User {
v, err := ucb.Save(ctx)
if err != nil {
panic(err)
}
return v
}
// Exec executes the query.
func (ucb *UserCreateBulk) Exec(ctx context.Context) error {
_, err := ucb.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (ucb *UserCreateBulk) ExecX(ctx context.Context) {
if err := ucb.Exec(ctx); err != nil {
panic(err)
}
}

View File

@ -1,89 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"git.grosinger.net/tgrosinger/saasitone/ent/predicate"
"git.grosinger.net/tgrosinger/saasitone/ent/user"
)
// UserDelete is the builder for deleting a User entity.
type UserDelete struct {
config
hooks []Hook
mutation *UserMutation
}
// Where appends a list predicates to the UserDelete builder.
func (ud *UserDelete) Where(ps ...predicate.User) *UserDelete {
ud.mutation.Where(ps...)
return ud
}
// Exec executes the deletion query and returns how many vertices were deleted.
func (ud *UserDelete) Exec(ctx context.Context) (int, error) {
return withHooks(ctx, ud.sqlExec, ud.mutation, ud.hooks)
}
// ExecX is like Exec, but panics if an error occurs.
func (ud *UserDelete) ExecX(ctx context.Context) int {
n, err := ud.Exec(ctx)
if err != nil {
panic(err)
}
return n
}
func (ud *UserDelete) sqlExec(ctx context.Context) (int, error) {
_spec := sqlgraph.NewDeleteSpec(user.Table, sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt))
if ps := ud.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
affected, err := sqlgraph.DeleteNodes(ctx, ud.driver, _spec)
if err != nil && sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
ud.mutation.done = true
return affected, err
}
// UserDeleteOne is the builder for deleting a single User entity.
type UserDeleteOne struct {
ud *UserDelete
}
// Where appends a list predicates to the UserDelete builder.
func (udo *UserDeleteOne) Where(ps ...predicate.User) *UserDeleteOne {
udo.ud.mutation.Where(ps...)
return udo
}
// Exec executes the deletion query.
func (udo *UserDeleteOne) Exec(ctx context.Context) error {
n, err := udo.ud.Exec(ctx)
switch {
case err != nil:
return err
case n == 0:
return &NotFoundError{user.Label}
default:
return nil
}
}
// ExecX is like Exec, but panics if an error occurs.
func (udo *UserDeleteOne) ExecX(ctx context.Context) {
if err := udo.Exec(ctx); err != nil {
panic(err)
}
}

View File

@ -1,607 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"database/sql/driver"
"fmt"
"math"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"git.grosinger.net/tgrosinger/saasitone/ent/passwordtoken"
"git.grosinger.net/tgrosinger/saasitone/ent/predicate"
"git.grosinger.net/tgrosinger/saasitone/ent/user"
)
// UserQuery is the builder for querying User entities.
type UserQuery struct {
config
ctx *QueryContext
order []user.OrderOption
inters []Interceptor
predicates []predicate.User
withOwner *PasswordTokenQuery
// intermediate query (i.e. traversal path).
sql *sql.Selector
path func(context.Context) (*sql.Selector, error)
}
// Where adds a new predicate for the UserQuery builder.
func (uq *UserQuery) Where(ps ...predicate.User) *UserQuery {
uq.predicates = append(uq.predicates, ps...)
return uq
}
// Limit the number of records to be returned by this query.
func (uq *UserQuery) Limit(limit int) *UserQuery {
uq.ctx.Limit = &limit
return uq
}
// Offset to start from.
func (uq *UserQuery) Offset(offset int) *UserQuery {
uq.ctx.Offset = &offset
return uq
}
// Unique configures the query builder to filter duplicate records on query.
// By default, unique is set to true, and can be disabled using this method.
func (uq *UserQuery) Unique(unique bool) *UserQuery {
uq.ctx.Unique = &unique
return uq
}
// Order specifies how the records should be ordered.
func (uq *UserQuery) Order(o ...user.OrderOption) *UserQuery {
uq.order = append(uq.order, o...)
return uq
}
// QueryOwner chains the current query on the "owner" edge.
func (uq *UserQuery) QueryOwner() *PasswordTokenQuery {
query := (&PasswordTokenClient{config: uq.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := uq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := uq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(user.Table, user.FieldID, selector),
sqlgraph.To(passwordtoken.Table, passwordtoken.FieldID),
sqlgraph.Edge(sqlgraph.O2M, true, user.OwnerTable, user.OwnerColumn),
)
fromU = sqlgraph.SetNeighbors(uq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// First returns the first User entity from the query.
// Returns a *NotFoundError when no User was found.
func (uq *UserQuery) First(ctx context.Context) (*User, error) {
nodes, err := uq.Limit(1).All(setContextOp(ctx, uq.ctx, "First"))
if err != nil {
return nil, err
}
if len(nodes) == 0 {
return nil, &NotFoundError{user.Label}
}
return nodes[0], nil
}
// FirstX is like First, but panics if an error occurs.
func (uq *UserQuery) FirstX(ctx context.Context) *User {
node, err := uq.First(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return node
}
// FirstID returns the first User ID from the query.
// Returns a *NotFoundError when no User ID was found.
func (uq *UserQuery) FirstID(ctx context.Context) (id int, err error) {
var ids []int
if ids, err = uq.Limit(1).IDs(setContextOp(ctx, uq.ctx, "FirstID")); err != nil {
return
}
if len(ids) == 0 {
err = &NotFoundError{user.Label}
return
}
return ids[0], nil
}
// FirstIDX is like FirstID, but panics if an error occurs.
func (uq *UserQuery) FirstIDX(ctx context.Context) int {
id, err := uq.FirstID(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return id
}
// Only returns a single User entity found by the query, ensuring it only returns one.
// Returns a *NotSingularError when more than one User entity is found.
// Returns a *NotFoundError when no User entities are found.
func (uq *UserQuery) Only(ctx context.Context) (*User, error) {
nodes, err := uq.Limit(2).All(setContextOp(ctx, uq.ctx, "Only"))
if err != nil {
return nil, err
}
switch len(nodes) {
case 1:
return nodes[0], nil
case 0:
return nil, &NotFoundError{user.Label}
default:
return nil, &NotSingularError{user.Label}
}
}
// OnlyX is like Only, but panics if an error occurs.
func (uq *UserQuery) OnlyX(ctx context.Context) *User {
node, err := uq.Only(ctx)
if err != nil {
panic(err)
}
return node
}
// OnlyID is like Only, but returns the only User ID in the query.
// Returns a *NotSingularError when more than one User ID is found.
// Returns a *NotFoundError when no entities are found.
func (uq *UserQuery) OnlyID(ctx context.Context) (id int, err error) {
var ids []int
if ids, err = uq.Limit(2).IDs(setContextOp(ctx, uq.ctx, "OnlyID")); err != nil {
return
}
switch len(ids) {
case 1:
id = ids[0]
case 0:
err = &NotFoundError{user.Label}
default:
err = &NotSingularError{user.Label}
}
return
}
// OnlyIDX is like OnlyID, but panics if an error occurs.
func (uq *UserQuery) OnlyIDX(ctx context.Context) int {
id, err := uq.OnlyID(ctx)
if err != nil {
panic(err)
}
return id
}
// All executes the query and returns a list of Users.
func (uq *UserQuery) All(ctx context.Context) ([]*User, error) {
ctx = setContextOp(ctx, uq.ctx, "All")
if err := uq.prepareQuery(ctx); err != nil {
return nil, err
}
qr := querierAll[[]*User, *UserQuery]()
return withInterceptors[[]*User](ctx, uq, qr, uq.inters)
}
// AllX is like All, but panics if an error occurs.
func (uq *UserQuery) AllX(ctx context.Context) []*User {
nodes, err := uq.All(ctx)
if err != nil {
panic(err)
}
return nodes
}
// IDs executes the query and returns a list of User IDs.
func (uq *UserQuery) IDs(ctx context.Context) (ids []int, err error) {
if uq.ctx.Unique == nil && uq.path != nil {
uq.Unique(true)
}
ctx = setContextOp(ctx, uq.ctx, "IDs")
if err = uq.Select(user.FieldID).Scan(ctx, &ids); err != nil {
return nil, err
}
return ids, nil
}
// IDsX is like IDs, but panics if an error occurs.
func (uq *UserQuery) IDsX(ctx context.Context) []int {
ids, err := uq.IDs(ctx)
if err != nil {
panic(err)
}
return ids
}
// Count returns the count of the given query.
func (uq *UserQuery) Count(ctx context.Context) (int, error) {
ctx = setContextOp(ctx, uq.ctx, "Count")
if err := uq.prepareQuery(ctx); err != nil {
return 0, err
}
return withInterceptors[int](ctx, uq, querierCount[*UserQuery](), uq.inters)
}
// CountX is like Count, but panics if an error occurs.
func (uq *UserQuery) CountX(ctx context.Context) int {
count, err := uq.Count(ctx)
if err != nil {
panic(err)
}
return count
}
// Exist returns true if the query has elements in the graph.
func (uq *UserQuery) Exist(ctx context.Context) (bool, error) {
ctx = setContextOp(ctx, uq.ctx, "Exist")
switch _, err := uq.FirstID(ctx); {
case IsNotFound(err):
return false, nil
case err != nil:
return false, fmt.Errorf("ent: check existence: %w", err)
default:
return true, nil
}
}
// ExistX is like Exist, but panics if an error occurs.
func (uq *UserQuery) ExistX(ctx context.Context) bool {
exist, err := uq.Exist(ctx)
if err != nil {
panic(err)
}
return exist
}
// Clone returns a duplicate of the UserQuery builder, including all associated steps. It can be
// used to prepare common query builders and use them differently after the clone is made.
func (uq *UserQuery) Clone() *UserQuery {
if uq == nil {
return nil
}
return &UserQuery{
config: uq.config,
ctx: uq.ctx.Clone(),
order: append([]user.OrderOption{}, uq.order...),
inters: append([]Interceptor{}, uq.inters...),
predicates: append([]predicate.User{}, uq.predicates...),
withOwner: uq.withOwner.Clone(),
// clone intermediate query.
sql: uq.sql.Clone(),
path: uq.path,
}
}
// WithOwner tells the query-builder to eager-load the nodes that are connected to
// the "owner" edge. The optional arguments are used to configure the query builder of the edge.
func (uq *UserQuery) WithOwner(opts ...func(*PasswordTokenQuery)) *UserQuery {
query := (&PasswordTokenClient{config: uq.config}).Query()
for _, opt := range opts {
opt(query)
}
uq.withOwner = query
return uq
}
// GroupBy is used to group vertices by one or more fields/columns.
// It is often used with aggregate functions, like: count, max, mean, min, sum.
//
// Example:
//
// var v []struct {
// Name string `json:"name,omitempty"`
// Count int `json:"count,omitempty"`
// }
//
// client.User.Query().
// GroupBy(user.FieldName).
// Aggregate(ent.Count()).
// Scan(ctx, &v)
func (uq *UserQuery) GroupBy(field string, fields ...string) *UserGroupBy {
uq.ctx.Fields = append([]string{field}, fields...)
grbuild := &UserGroupBy{build: uq}
grbuild.flds = &uq.ctx.Fields
grbuild.label = user.Label
grbuild.scan = grbuild.Scan
return grbuild
}
// Select allows the selection one or more fields/columns for the given query,
// instead of selecting all fields in the entity.
//
// Example:
//
// var v []struct {
// Name string `json:"name,omitempty"`
// }
//
// client.User.Query().
// Select(user.FieldName).
// Scan(ctx, &v)
func (uq *UserQuery) Select(fields ...string) *UserSelect {
uq.ctx.Fields = append(uq.ctx.Fields, fields...)
sbuild := &UserSelect{UserQuery: uq}
sbuild.label = user.Label
sbuild.flds, sbuild.scan = &uq.ctx.Fields, sbuild.Scan
return sbuild
}
// Aggregate returns a UserSelect configured with the given aggregations.
func (uq *UserQuery) Aggregate(fns ...AggregateFunc) *UserSelect {
return uq.Select().Aggregate(fns...)
}
func (uq *UserQuery) prepareQuery(ctx context.Context) error {
for _, inter := range uq.inters {
if inter == nil {
return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)")
}
if trv, ok := inter.(Traverser); ok {
if err := trv.Traverse(ctx, uq); err != nil {
return err
}
}
}
for _, f := range uq.ctx.Fields {
if !user.ValidColumn(f) {
return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
}
}
if uq.path != nil {
prev, err := uq.path(ctx)
if err != nil {
return err
}
uq.sql = prev
}
return nil
}
func (uq *UserQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*User, error) {
var (
nodes = []*User{}
_spec = uq.querySpec()
loadedTypes = [1]bool{
uq.withOwner != nil,
}
)
_spec.ScanValues = func(columns []string) ([]any, error) {
return (*User).scanValues(nil, columns)
}
_spec.Assign = func(columns []string, values []any) error {
node := &User{config: uq.config}
nodes = append(nodes, node)
node.Edges.loadedTypes = loadedTypes
return node.assignValues(columns, values)
}
for i := range hooks {
hooks[i](ctx, _spec)
}
if err := sqlgraph.QueryNodes(ctx, uq.driver, _spec); err != nil {
return nil, err
}
if len(nodes) == 0 {
return nodes, nil
}
if query := uq.withOwner; query != nil {
if err := uq.loadOwner(ctx, query, nodes,
func(n *User) { n.Edges.Owner = []*PasswordToken{} },
func(n *User, e *PasswordToken) { n.Edges.Owner = append(n.Edges.Owner, e) }); err != nil {
return nil, err
}
}
return nodes, nil
}
func (uq *UserQuery) loadOwner(ctx context.Context, query *PasswordTokenQuery, nodes []*User, init func(*User), assign func(*User, *PasswordToken)) error {
fks := make([]driver.Value, 0, len(nodes))
nodeids := make(map[int]*User)
for i := range nodes {
fks = append(fks, nodes[i].ID)
nodeids[nodes[i].ID] = nodes[i]
if init != nil {
init(nodes[i])
}
}
query.withFKs = true
query.Where(predicate.PasswordToken(func(s *sql.Selector) {
s.Where(sql.InValues(s.C(user.OwnerColumn), fks...))
}))
neighbors, err := query.All(ctx)
if err != nil {
return err
}
for _, n := range neighbors {
fk := n.password_token_user
if fk == nil {
return fmt.Errorf(`foreign-key "password_token_user" is nil for node %v`, n.ID)
}
node, ok := nodeids[*fk]
if !ok {
return fmt.Errorf(`unexpected referenced foreign-key "password_token_user" returned %v for node %v`, *fk, n.ID)
}
assign(node, n)
}
return nil
}
func (uq *UserQuery) sqlCount(ctx context.Context) (int, error) {
_spec := uq.querySpec()
_spec.Node.Columns = uq.ctx.Fields
if len(uq.ctx.Fields) > 0 {
_spec.Unique = uq.ctx.Unique != nil && *uq.ctx.Unique
}
return sqlgraph.CountNodes(ctx, uq.driver, _spec)
}
func (uq *UserQuery) querySpec() *sqlgraph.QuerySpec {
_spec := sqlgraph.NewQuerySpec(user.Table, user.Columns, sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt))
_spec.From = uq.sql
if unique := uq.ctx.Unique; unique != nil {
_spec.Unique = *unique
} else if uq.path != nil {
_spec.Unique = true
}
if fields := uq.ctx.Fields; len(fields) > 0 {
_spec.Node.Columns = make([]string, 0, len(fields))
_spec.Node.Columns = append(_spec.Node.Columns, user.FieldID)
for i := range fields {
if fields[i] != user.FieldID {
_spec.Node.Columns = append(_spec.Node.Columns, fields[i])
}
}
}
if ps := uq.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if limit := uq.ctx.Limit; limit != nil {
_spec.Limit = *limit
}
if offset := uq.ctx.Offset; offset != nil {
_spec.Offset = *offset
}
if ps := uq.order; len(ps) > 0 {
_spec.Order = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
return _spec
}
func (uq *UserQuery) sqlQuery(ctx context.Context) *sql.Selector {
builder := sql.Dialect(uq.driver.Dialect())
t1 := builder.Table(user.Table)
columns := uq.ctx.Fields
if len(columns) == 0 {
columns = user.Columns
}
selector := builder.Select(t1.Columns(columns...)...).From(t1)
if uq.sql != nil {
selector = uq.sql
selector.Select(selector.Columns(columns...)...)
}
if uq.ctx.Unique != nil && *uq.ctx.Unique {
selector.Distinct()
}
for _, p := range uq.predicates {
p(selector)
}
for _, p := range uq.order {
p(selector)
}
if offset := uq.ctx.Offset; offset != nil {
// limit is mandatory for offset clause. We start
// with default value, and override it below if needed.
selector.Offset(*offset).Limit(math.MaxInt32)
}
if limit := uq.ctx.Limit; limit != nil {
selector.Limit(*limit)
}
return selector
}
// UserGroupBy is the group-by builder for User entities.
type UserGroupBy struct {
selector
build *UserQuery
}
// Aggregate adds the given aggregation functions to the group-by query.
func (ugb *UserGroupBy) Aggregate(fns ...AggregateFunc) *UserGroupBy {
ugb.fns = append(ugb.fns, fns...)
return ugb
}
// Scan applies the selector query and scans the result into the given value.
func (ugb *UserGroupBy) Scan(ctx context.Context, v any) error {
ctx = setContextOp(ctx, ugb.build.ctx, "GroupBy")
if err := ugb.build.prepareQuery(ctx); err != nil {
return err
}
return scanWithInterceptors[*UserQuery, *UserGroupBy](ctx, ugb.build, ugb, ugb.build.inters, v)
}
func (ugb *UserGroupBy) sqlScan(ctx context.Context, root *UserQuery, v any) error {
selector := root.sqlQuery(ctx).Select()
aggregation := make([]string, 0, len(ugb.fns))
for _, fn := range ugb.fns {
aggregation = append(aggregation, fn(selector))
}
if len(selector.SelectedColumns()) == 0 {
columns := make([]string, 0, len(*ugb.flds)+len(ugb.fns))
for _, f := range *ugb.flds {
columns = append(columns, selector.C(f))
}
columns = append(columns, aggregation...)
selector.Select(columns...)
}
selector.GroupBy(selector.Columns(*ugb.flds...)...)
if err := selector.Err(); err != nil {
return err
}
rows := &sql.Rows{}
query, args := selector.Query()
if err := ugb.build.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}
// UserSelect is the builder for selecting fields of User entities.
type UserSelect struct {
*UserQuery
selector
}
// Aggregate adds the given aggregation functions to the selector query.
func (us *UserSelect) Aggregate(fns ...AggregateFunc) *UserSelect {
us.fns = append(us.fns, fns...)
return us
}
// Scan applies the selector query and scans the result into the given value.
func (us *UserSelect) Scan(ctx context.Context, v any) error {
ctx = setContextOp(ctx, us.ctx, "Select")
if err := us.prepareQuery(ctx); err != nil {
return err
}
return scanWithInterceptors[*UserQuery, *UserSelect](ctx, us.UserQuery, us, us.inters, v)
}
func (us *UserSelect) sqlScan(ctx context.Context, root *UserQuery, v any) error {
selector := root.sqlQuery(ctx)
aggregation := make([]string, 0, len(us.fns))
for _, fn := range us.fns {
aggregation = append(aggregation, fn(selector))
}
switch n := len(*us.selector.flds); {
case n == 0 && len(aggregation) > 0:
selector.Select(aggregation...)
case n != 0 && len(aggregation) > 0:
selector.AppendSelect(aggregation...)
}
rows := &sql.Rows{}
query, args := selector.Query()
if err := us.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}

View File

@ -1,521 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"errors"
"fmt"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"git.grosinger.net/tgrosinger/saasitone/ent/passwordtoken"
"git.grosinger.net/tgrosinger/saasitone/ent/predicate"
"git.grosinger.net/tgrosinger/saasitone/ent/user"
)
// UserUpdate is the builder for updating User entities.
type UserUpdate struct {
config
hooks []Hook
mutation *UserMutation
}
// Where appends a list predicates to the UserUpdate builder.
func (uu *UserUpdate) Where(ps ...predicate.User) *UserUpdate {
uu.mutation.Where(ps...)
return uu
}
// SetName sets the "name" field.
func (uu *UserUpdate) SetName(s string) *UserUpdate {
uu.mutation.SetName(s)
return uu
}
// SetNillableName sets the "name" field if the given value is not nil.
func (uu *UserUpdate) SetNillableName(s *string) *UserUpdate {
if s != nil {
uu.SetName(*s)
}
return uu
}
// SetEmail sets the "email" field.
func (uu *UserUpdate) SetEmail(s string) *UserUpdate {
uu.mutation.SetEmail(s)
return uu
}
// SetNillableEmail sets the "email" field if the given value is not nil.
func (uu *UserUpdate) SetNillableEmail(s *string) *UserUpdate {
if s != nil {
uu.SetEmail(*s)
}
return uu
}
// SetPassword sets the "password" field.
func (uu *UserUpdate) SetPassword(s string) *UserUpdate {
uu.mutation.SetPassword(s)
return uu
}
// SetNillablePassword sets the "password" field if the given value is not nil.
func (uu *UserUpdate) SetNillablePassword(s *string) *UserUpdate {
if s != nil {
uu.SetPassword(*s)
}
return uu
}
// SetVerified sets the "verified" field.
func (uu *UserUpdate) SetVerified(b bool) *UserUpdate {
uu.mutation.SetVerified(b)
return uu
}
// SetNillableVerified sets the "verified" field if the given value is not nil.
func (uu *UserUpdate) SetNillableVerified(b *bool) *UserUpdate {
if b != nil {
uu.SetVerified(*b)
}
return uu
}
// AddOwnerIDs adds the "owner" edge to the PasswordToken entity by IDs.
func (uu *UserUpdate) AddOwnerIDs(ids ...int) *UserUpdate {
uu.mutation.AddOwnerIDs(ids...)
return uu
}
// AddOwner adds the "owner" edges to the PasswordToken entity.
func (uu *UserUpdate) AddOwner(p ...*PasswordToken) *UserUpdate {
ids := make([]int, len(p))
for i := range p {
ids[i] = p[i].ID
}
return uu.AddOwnerIDs(ids...)
}
// Mutation returns the UserMutation object of the builder.
func (uu *UserUpdate) Mutation() *UserMutation {
return uu.mutation
}
// ClearOwner clears all "owner" edges to the PasswordToken entity.
func (uu *UserUpdate) ClearOwner() *UserUpdate {
uu.mutation.ClearOwner()
return uu
}
// RemoveOwnerIDs removes the "owner" edge to PasswordToken entities by IDs.
func (uu *UserUpdate) RemoveOwnerIDs(ids ...int) *UserUpdate {
uu.mutation.RemoveOwnerIDs(ids...)
return uu
}
// RemoveOwner removes "owner" edges to PasswordToken entities.
func (uu *UserUpdate) RemoveOwner(p ...*PasswordToken) *UserUpdate {
ids := make([]int, len(p))
for i := range p {
ids[i] = p[i].ID
}
return uu.RemoveOwnerIDs(ids...)
}
// Save executes the query and returns the number of nodes affected by the update operation.
func (uu *UserUpdate) Save(ctx context.Context) (int, error) {
return withHooks(ctx, uu.sqlSave, uu.mutation, uu.hooks)
}
// SaveX is like Save, but panics if an error occurs.
func (uu *UserUpdate) SaveX(ctx context.Context) int {
affected, err := uu.Save(ctx)
if err != nil {
panic(err)
}
return affected
}
// Exec executes the query.
func (uu *UserUpdate) Exec(ctx context.Context) error {
_, err := uu.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (uu *UserUpdate) ExecX(ctx context.Context) {
if err := uu.Exec(ctx); err != nil {
panic(err)
}
}
// check runs all checks and user-defined validators on the builder.
func (uu *UserUpdate) check() error {
if v, ok := uu.mutation.Name(); ok {
if err := user.NameValidator(v); err != nil {
return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "User.name": %w`, err)}
}
}
if v, ok := uu.mutation.Email(); ok {
if err := user.EmailValidator(v); err != nil {
return &ValidationError{Name: "email", err: fmt.Errorf(`ent: validator failed for field "User.email": %w`, err)}
}
}
if v, ok := uu.mutation.Password(); ok {
if err := user.PasswordValidator(v); err != nil {
return &ValidationError{Name: "password", err: fmt.Errorf(`ent: validator failed for field "User.password": %w`, err)}
}
}
return nil
}
func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) {
if err := uu.check(); err != nil {
return n, err
}
_spec := sqlgraph.NewUpdateSpec(user.Table, user.Columns, sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt))
if ps := uu.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if value, ok := uu.mutation.Name(); ok {
_spec.SetField(user.FieldName, field.TypeString, value)
}
if value, ok := uu.mutation.Email(); ok {
_spec.SetField(user.FieldEmail, field.TypeString, value)
}
if value, ok := uu.mutation.Password(); ok {
_spec.SetField(user.FieldPassword, field.TypeString, value)
}
if value, ok := uu.mutation.Verified(); ok {
_spec.SetField(user.FieldVerified, field.TypeBool, value)
}
if uu.mutation.OwnerCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: user.OwnerTable,
Columns: []string{user.OwnerColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(passwordtoken.FieldID, field.TypeInt),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := uu.mutation.RemovedOwnerIDs(); len(nodes) > 0 && !uu.mutation.OwnerCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: user.OwnerTable,
Columns: []string{user.OwnerColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(passwordtoken.FieldID, field.TypeInt),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := uu.mutation.OwnerIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: user.OwnerTable,
Columns: []string{user.OwnerColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(passwordtoken.FieldID, field.TypeInt),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if n, err = sqlgraph.UpdateNodes(ctx, uu.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{user.Label}
} else if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
return 0, err
}
uu.mutation.done = true
return n, nil
}
// UserUpdateOne is the builder for updating a single User entity.
type UserUpdateOne struct {
config
fields []string
hooks []Hook
mutation *UserMutation
}
// SetName sets the "name" field.
func (uuo *UserUpdateOne) SetName(s string) *UserUpdateOne {
uuo.mutation.SetName(s)
return uuo
}
// SetNillableName sets the "name" field if the given value is not nil.
func (uuo *UserUpdateOne) SetNillableName(s *string) *UserUpdateOne {
if s != nil {
uuo.SetName(*s)
}
return uuo
}
// SetEmail sets the "email" field.
func (uuo *UserUpdateOne) SetEmail(s string) *UserUpdateOne {
uuo.mutation.SetEmail(s)
return uuo
}
// SetNillableEmail sets the "email" field if the given value is not nil.
func (uuo *UserUpdateOne) SetNillableEmail(s *string) *UserUpdateOne {
if s != nil {
uuo.SetEmail(*s)
}
return uuo
}
// SetPassword sets the "password" field.
func (uuo *UserUpdateOne) SetPassword(s string) *UserUpdateOne {
uuo.mutation.SetPassword(s)
return uuo
}
// SetNillablePassword sets the "password" field if the given value is not nil.
func (uuo *UserUpdateOne) SetNillablePassword(s *string) *UserUpdateOne {
if s != nil {
uuo.SetPassword(*s)
}
return uuo
}
// SetVerified sets the "verified" field.
func (uuo *UserUpdateOne) SetVerified(b bool) *UserUpdateOne {
uuo.mutation.SetVerified(b)
return uuo
}
// SetNillableVerified sets the "verified" field if the given value is not nil.
func (uuo *UserUpdateOne) SetNillableVerified(b *bool) *UserUpdateOne {
if b != nil {
uuo.SetVerified(*b)
}
return uuo
}
// AddOwnerIDs adds the "owner" edge to the PasswordToken entity by IDs.
func (uuo *UserUpdateOne) AddOwnerIDs(ids ...int) *UserUpdateOne {
uuo.mutation.AddOwnerIDs(ids...)
return uuo
}
// AddOwner adds the "owner" edges to the PasswordToken entity.
func (uuo *UserUpdateOne) AddOwner(p ...*PasswordToken) *UserUpdateOne {
ids := make([]int, len(p))
for i := range p {
ids[i] = p[i].ID
}
return uuo.AddOwnerIDs(ids...)
}
// Mutation returns the UserMutation object of the builder.
func (uuo *UserUpdateOne) Mutation() *UserMutation {
return uuo.mutation
}
// ClearOwner clears all "owner" edges to the PasswordToken entity.
func (uuo *UserUpdateOne) ClearOwner() *UserUpdateOne {
uuo.mutation.ClearOwner()
return uuo
}
// RemoveOwnerIDs removes the "owner" edge to PasswordToken entities by IDs.
func (uuo *UserUpdateOne) RemoveOwnerIDs(ids ...int) *UserUpdateOne {
uuo.mutation.RemoveOwnerIDs(ids...)
return uuo
}
// RemoveOwner removes "owner" edges to PasswordToken entities.
func (uuo *UserUpdateOne) RemoveOwner(p ...*PasswordToken) *UserUpdateOne {
ids := make([]int, len(p))
for i := range p {
ids[i] = p[i].ID
}
return uuo.RemoveOwnerIDs(ids...)
}
// Where appends a list predicates to the UserUpdate builder.
func (uuo *UserUpdateOne) Where(ps ...predicate.User) *UserUpdateOne {
uuo.mutation.Where(ps...)
return uuo
}
// Select allows selecting one or more fields (columns) of the returned entity.
// The default is selecting all fields defined in the entity schema.
func (uuo *UserUpdateOne) Select(field string, fields ...string) *UserUpdateOne {
uuo.fields = append([]string{field}, fields...)
return uuo
}
// Save executes the query and returns the updated User entity.
func (uuo *UserUpdateOne) Save(ctx context.Context) (*User, error) {
return withHooks(ctx, uuo.sqlSave, uuo.mutation, uuo.hooks)
}
// SaveX is like Save, but panics if an error occurs.
func (uuo *UserUpdateOne) SaveX(ctx context.Context) *User {
node, err := uuo.Save(ctx)
if err != nil {
panic(err)
}
return node
}
// Exec executes the query on the entity.
func (uuo *UserUpdateOne) Exec(ctx context.Context) error {
_, err := uuo.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (uuo *UserUpdateOne) ExecX(ctx context.Context) {
if err := uuo.Exec(ctx); err != nil {
panic(err)
}
}
// check runs all checks and user-defined validators on the builder.
func (uuo *UserUpdateOne) check() error {
if v, ok := uuo.mutation.Name(); ok {
if err := user.NameValidator(v); err != nil {
return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "User.name": %w`, err)}
}
}
if v, ok := uuo.mutation.Email(); ok {
if err := user.EmailValidator(v); err != nil {
return &ValidationError{Name: "email", err: fmt.Errorf(`ent: validator failed for field "User.email": %w`, err)}
}
}
if v, ok := uuo.mutation.Password(); ok {
if err := user.PasswordValidator(v); err != nil {
return &ValidationError{Name: "password", err: fmt.Errorf(`ent: validator failed for field "User.password": %w`, err)}
}
}
return nil
}
func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (_node *User, err error) {
if err := uuo.check(); err != nil {
return _node, err
}
_spec := sqlgraph.NewUpdateSpec(user.Table, user.Columns, sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt))
id, ok := uuo.mutation.ID()
if !ok {
return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "User.id" for update`)}
}
_spec.Node.ID.Value = id
if fields := uuo.fields; len(fields) > 0 {
_spec.Node.Columns = make([]string, 0, len(fields))
_spec.Node.Columns = append(_spec.Node.Columns, user.FieldID)
for _, f := range fields {
if !user.ValidColumn(f) {
return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
}
if f != user.FieldID {
_spec.Node.Columns = append(_spec.Node.Columns, f)
}
}
}
if ps := uuo.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if value, ok := uuo.mutation.Name(); ok {
_spec.SetField(user.FieldName, field.TypeString, value)
}
if value, ok := uuo.mutation.Email(); ok {
_spec.SetField(user.FieldEmail, field.TypeString, value)
}
if value, ok := uuo.mutation.Password(); ok {
_spec.SetField(user.FieldPassword, field.TypeString, value)
}
if value, ok := uuo.mutation.Verified(); ok {
_spec.SetField(user.FieldVerified, field.TypeBool, value)
}
if uuo.mutation.OwnerCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: user.OwnerTable,
Columns: []string{user.OwnerColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(passwordtoken.FieldID, field.TypeInt),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := uuo.mutation.RemovedOwnerIDs(); len(nodes) > 0 && !uuo.mutation.OwnerCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: user.OwnerTable,
Columns: []string{user.OwnerColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(passwordtoken.FieldID, field.TypeInt),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := uuo.mutation.OwnerIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: user.OwnerTable,
Columns: []string{user.OwnerColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(passwordtoken.FieldID, field.TypeInt),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
_node = &User{config: uuo.config}
_spec.Assign = _node.assignValues
_spec.ScanValues = _node.scanValues
if err = sqlgraph.UpdateNode(ctx, uuo.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{user.Label}
} else if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
return nil, err
}
uuo.mutation.done = true
return _node, nil
}

8
go.mod
View File

@ -37,21 +37,27 @@ require (
github.com/go-openapi/inflect v0.21.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/golang-migrate/migrate/v4 v4.17.1 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/securecookie v1.1.2 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hashicorp/hcl/v2 v2.20.1 // indirect
github.com/huandu/xstrings v1.4.0 // indirect
github.com/imdario/mergo v0.3.16 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/rogpeppe/go-internal v1.10.0 // indirect
@ -60,11 +66,13 @@ require (
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/cobra v1.7.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
github.com/zclconf/go-cty v1.14.4 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/exp v0.0.0-20240707233637-46b078467d37 // indirect
golang.org/x/mod v0.19.0 // indirect

21
go.sum
View File

@ -20,6 +20,7 @@ github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsVi
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY=
github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
@ -52,6 +53,8 @@ github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang-migrate/migrate/v4 v4.17.1 h1:4zQ6iqL6t6AiItphxJctQb3cFqWiSpMnX7wLTPnnYO4=
github.com/golang-migrate/migrate/v4 v4.17.1/go.mod h1:m8hinFyWBn0SA4QKHuKh175Pm9wjmxj3S2Mia7dbXzM=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
@ -66,6 +69,11 @@ github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTj
github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ=
github.com/gorilla/sessions v1.3.0 h1:XYlkq7KcpOB2ZhHBPv5WpjMIxrQosiZanfoy1HLZFzg=
github.com/gorilla/sessions v1.3.0/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/hcl/v2 v2.20.1 h1:M6hgdyz7HYt1UN9e61j+qKJBqR3orTWbI1HKBJEdxtc=
@ -74,6 +82,8 @@ github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU
github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
@ -98,6 +108,8 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/maypok86/otter v1.2.1 h1:xyvMW+t0vE1sKt/++GTkznLitEl7D/msqXkAbLwiC1M=
@ -110,6 +122,8 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/pelletier/go-toml/v2 v2.2.1 h1:9TA9+T8+8CUCO2+WYnDLCgrYi9+omqKXyjDtosvtEhg=
github.com/pelletier/go-toml/v2 v2.2.1/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
@ -119,6 +133,7 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
github.com/sagikazarmark/locafero v0.6.0 h1:ON7AQg37yzcRPU69mt7gwhFEBwxI6P9T4Qu3N51bwOk=
@ -131,6 +146,8 @@ github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=
@ -141,6 +158,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
@ -157,6 +175,8 @@ github.com/zclconf/go-cty v1.14.4 h1:uXXczd9QDGsgu0i/QFR/hzI5NYCHLf6NQw/atrbnhq8
github.com/zclconf/go-cty v1.14.4/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE=
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b h1:FosyBZYxY34Wul7O/MSKey3txpPYyCqVO5ZyceuQJEI=
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@ -224,6 +244,7 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY=
golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

37
pkg/db/time.go Normal file
View File

@ -0,0 +1,37 @@
package db
import (
"database/sql/driver"
"errors"
"time"
)
const timeFormat = "2006-01-02 15:04:05"
type Time struct {
time.Time
}
func (t *Time) Scan(value any) error {
valueStr := ""
switch s := value.(type) {
case string:
valueStr = s
case []byte:
valueStr = string(s)
default:
return errors.New("Cannot scan value into Time")
}
parsedTime, err := time.Parse(timeFormat, valueStr)
if err != nil {
return err
}
t.Time = parsedTime
return nil
}
func (t Time) Value() (driver.Value, error) {
return t.Format(timeFormat), nil
}

View File

@ -1,18 +1,19 @@
package handlers
import (
"database/sql"
"fmt"
"strings"
"github.com/go-playground/validator/v10"
"github.com/labstack/echo/v4"
"git.grosinger.net/tgrosinger/saasitone/ent"
"git.grosinger.net/tgrosinger/saasitone/ent/user"
"git.grosinger.net/tgrosinger/saasitone/pkg/context"
"git.grosinger.net/tgrosinger/saasitone/pkg/form"
"git.grosinger.net/tgrosinger/saasitone/pkg/log"
"git.grosinger.net/tgrosinger/saasitone/pkg/middleware"
"git.grosinger.net/tgrosinger/saasitone/pkg/models"
"git.grosinger.net/tgrosinger/saasitone/pkg/models/sqlc"
"git.grosinger.net/tgrosinger/saasitone/pkg/msg"
"git.grosinger.net/tgrosinger/saasitone/pkg/page"
"git.grosinger.net/tgrosinger/saasitone/pkg/redirect"
@ -37,7 +38,7 @@ type (
Auth struct {
auth *services.AuthClient
mail *services.MailClient
orm *ent.Client
db *models.Client
*services.TemplateRenderer
}
@ -73,7 +74,7 @@ func init() {
func (h *Auth) Init(c *services.Container) error {
h.TemplateRenderer = c.TemplateRenderer
h.orm = c.ORM
h.db = c.DB
h.auth = c.Auth
h.mail = c.Mail
return nil
@ -92,7 +93,7 @@ func (h *Auth) Routes(g *echo.Group) {
noAuth.POST("/password", h.ForgotPasswordSubmit).Name = routeNameForgotPasswordSubmit
resetGroup := noAuth.Group("/password/reset",
middleware.LoadUser(h.orm),
middleware.LoadUser(h.db),
middleware.LoadValidPasswordToken(h.auth),
)
resetGroup.GET("/token/:user/:password_token/:token", h.ResetPasswordPage).Name = routeNameResetPassword
@ -129,16 +130,10 @@ func (h *Auth) ForgotPasswordSubmit(ctx echo.Context) error {
}
// Attempt to load the user
u, err := h.orm.User.
Query().
Where(user.Email(strings.ToLower(input.Email))).
Only(ctx.Request().Context())
switch err.(type) {
case *ent.NotFoundError:
u, err := h.db.C.GetUserByEmail(ctx.Request().Context(), strings.ToLower(input.Email))
if err == sql.ErrNoRows {
return succeed()
case nil:
default:
} else if err != nil {
return fail(err, "error querying user during forgot password")
}
@ -198,16 +193,10 @@ func (h *Auth) LoginSubmit(ctx echo.Context) error {
}
// Attempt to load the user
u, err := h.orm.User.
Query().
Where(user.Email(strings.ToLower(input.Email))).
Only(ctx.Request().Context())
switch err.(type) {
case *ent.NotFoundError:
u, err := h.db.C.GetUserByEmail(ctx.Request().Context(), strings.ToLower(input.Email))
if err == sql.ErrNoRows {
return authFailed()
case nil:
default:
} else if err != nil {
return fail(err, "error querying user during login")
}
@ -271,28 +260,27 @@ func (h *Auth) RegisterSubmit(ctx echo.Context) error {
}
// Attempt creating the user
u, err := h.orm.User.
Create().
SetName(input.Name).
SetEmail(input.Email).
SetPassword(pwHash).
Save(ctx.Request().Context())
u, err := h.db.C.CreateUser(ctx.Request().Context(), sqlc.CreateUserParams{
Name: input.Name,
Email: input.Email,
Password: pwHash,
})
if err != nil {
if strings.HasPrefix(err.Error(), "UNIQUE constraint failed") {
msg.Warning(ctx, "A user with this email address already exists. Please log in.")
return redirect.New(ctx).
Route(routeNameLogin).
Go()
}
switch err.(type) {
case nil:
log.Ctx(ctx).Info("user created",
"user_name", u.Name,
"user_id", u.ID,
)
case *ent.ConstraintError:
msg.Warning(ctx, "A user with this email address already exists. Please log in.")
return redirect.New(ctx).
Route(routeNameLogin).
Go()
default:
return fail(err, "unable to create user")
}
log.Ctx(ctx).Info("user created",
"user_name", u.Name,
"user_id", u.ID,
)
// Log the user in
err = h.auth.Login(ctx, u.ID)
if err != nil {
@ -316,7 +304,7 @@ func (h *Auth) RegisterSubmit(ctx echo.Context) error {
Go()
}
func (h *Auth) sendVerificationEmail(ctx echo.Context, usr *ent.User) {
func (h *Auth) sendVerificationEmail(ctx echo.Context, usr sqlc.User) {
// Generate a token
token, err := h.auth.GenerateEmailVerificationToken(usr.Email)
if err != nil {
@ -376,13 +364,13 @@ func (h *Auth) ResetPasswordSubmit(ctx echo.Context) error {
}
// Get the requesting user
usr := ctx.Get(context.UserKey).(*ent.User)
usr := ctx.Get(context.UserKey).(*sqlc.User)
// Update the user
_, err = usr.
Update().
SetPassword(hash).
Save(ctx.Request().Context())
err = h.db.C.UpdateUserPassword(ctx.Request().Context(), sqlc.UpdateUserPasswordParams{
Password: hash,
ID: usr.ID,
})
if err != nil {
return fail(err, "unable to update password")
}
@ -400,9 +388,6 @@ func (h *Auth) ResetPasswordSubmit(ctx echo.Context) error {
}
func (h *Auth) VerifyEmail(ctx echo.Context) error {
var usr *ent.User
// Validate the token
token := ctx.Param("token")
email, err := h.auth.ValidateEmailVerificationToken(token)
if err != nil {
@ -412,35 +397,9 @@ func (h *Auth) VerifyEmail(ctx echo.Context) error {
Go()
}
// Check if it matches the authenticated user
if u := ctx.Get(context.AuthenticatedUserKey); u != nil {
authUser := u.(*ent.User)
if authUser.Email == email {
usr = authUser
}
}
// Query to find a matching user, if needed
if usr == nil {
usr, err = h.orm.User.
Query().
Where(user.Email(email)).
Only(ctx.Request().Context())
if err != nil {
return fail(err, "query failed loading email verification token user")
}
}
// Verify the user, if needed
if !usr.Verified {
usr, err = usr.
Update().
SetVerified(true).
Save(ctx.Request().Context())
if err != nil {
return fail(err, "failed to set user as verified")
}
err = h.db.C.UpdateUserSetVerified(ctx.Request().Context(), email)
if err != nil {
return fail(err, "failed to set user as verified")
}
msg.Success(ctx, "Your email has been successfully verified.")

View File

@ -1,15 +1,15 @@
package middleware
import (
"errors"
"fmt"
"net/http"
"strconv"
"github.com/labstack/echo/v4"
"git.grosinger.net/tgrosinger/saasitone/ent"
"git.grosinger.net/tgrosinger/saasitone/pkg/context"
"git.grosinger.net/tgrosinger/saasitone/pkg/log"
"git.grosinger.net/tgrosinger/saasitone/pkg/models/sqlc"
"git.grosinger.net/tgrosinger/saasitone/pkg/msg"
"git.grosinger.net/tgrosinger/saasitone/pkg/services"
)
@ -19,17 +19,13 @@ func LoadAuthenticatedUser(authClient *services.AuthClient) echo.MiddlewareFunc
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
u, err := authClient.GetAuthenticatedUser(c)
switch err.(type) {
case *ent.NotFoundError:
log.Ctx(c).Warn("auth user not found")
case services.NotAuthenticatedError:
case nil:
c.Set(context.AuthenticatedUserKey, u)
default:
if err != nil && !errors.Is(err, services.NotAuthenticatedError{}) {
return echo.NewHTTPError(
http.StatusInternalServerError,
fmt.Sprintf("error querying for authenticated user: %v", err),
)
} else if u != nil {
c.Set(context.AuthenticatedUserKey, u)
}
return next(c)
@ -48,7 +44,7 @@ func LoadValidPasswordToken(authClient *services.AuthClient) echo.MiddlewareFunc
if c.Get(context.UserKey) == nil {
return echo.NewHTTPError(http.StatusInternalServerError)
}
usr := c.Get(context.UserKey).(*ent.User)
usr := c.Get(context.UserKey).(*sqlc.User)
// Extract the token ID
tokenID, err := strconv.Atoi(c.Param("password_token"))

View File

@ -8,9 +8,9 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"git.grosinger.net/tgrosinger/saasitone/ent"
"git.grosinger.net/tgrosinger/saasitone/pkg/context"
"git.grosinger.net/tgrosinger/saasitone/pkg/tests"
"git.grosinger.net/tgrosinger/saasitone/pkg/models/sqlc"
)
func TestLoadAuthenticatedUser(t *testing.T) {
@ -29,7 +29,7 @@ func TestLoadAuthenticatedUser(t *testing.T) {
// Verify the midldeware returns the authenticated user
_ = tests.ExecuteMiddleware(ctx, mw)
require.NotNil(t, ctx.Get(context.AuthenticatedUserKey))
ctxUsr, ok := ctx.Get(context.AuthenticatedUserKey).(*ent.User)
ctxUsr, ok := ctx.Get(context.AuthenticatedUserKey).(*sqlc.User)
require.True(t, ok)
assert.Equal(t, usr.ID, ctxUsr.ID)
}
@ -81,7 +81,7 @@ func TestLoadValidPasswordToken(t *testing.T) {
// Add user and password token context but no token and expect a redirect
ctx.SetParamNames("user", "password_token")
ctx.SetParamValues(fmt.Sprintf("%d", usr.ID), "1")
_ = tests.ExecuteMiddleware(ctx, LoadUser(c.ORM))
_ = tests.ExecuteMiddleware(ctx, LoadUser(c.DB))
err = tests.ExecuteMiddleware(ctx, LoadValidPasswordToken(c.Auth))
assert.NoError(t, err)
assert.Equal(t, http.StatusFound, ctx.Response().Status)
@ -89,7 +89,7 @@ func TestLoadValidPasswordToken(t *testing.T) {
// Add user context and invalid password token and expect a redirect
ctx.SetParamNames("user", "password_token", "token")
ctx.SetParamValues(fmt.Sprintf("%d", usr.ID), "1", "faketoken")
_ = tests.ExecuteMiddleware(ctx, LoadUser(c.ORM))
_ = tests.ExecuteMiddleware(ctx, LoadUser(c.DB))
err = tests.ExecuteMiddleware(ctx, LoadValidPasswordToken(c.Auth))
assert.NoError(t, err)
assert.Equal(t, http.StatusFound, ctx.Response().Status)
@ -101,10 +101,10 @@ func TestLoadValidPasswordToken(t *testing.T) {
// Add user and valid password token
ctx.SetParamNames("user", "password_token", "token")
ctx.SetParamValues(fmt.Sprintf("%d", usr.ID), fmt.Sprintf("%d", pt.ID), token)
_ = tests.ExecuteMiddleware(ctx, LoadUser(c.ORM))
_ = tests.ExecuteMiddleware(ctx, LoadUser(c.DB))
err = tests.ExecuteMiddleware(ctx, LoadValidPasswordToken(c.Auth))
assert.Nil(t, err)
ctxPt, ok := ctx.Get(context.PasswordTokenKey).(*ent.PasswordToken)
ctxPt, ok := ctx.Get(context.PasswordTokenKey).(*sqlc.PasswordToken)
require.True(t, ok)
assert.Equal(t, pt.ID, ctxPt.ID)
}

View File

@ -1,19 +1,19 @@
package middleware
import (
"database/sql"
"fmt"
"net/http"
"strconv"
"github.com/labstack/echo/v4"
"git.grosinger.net/tgrosinger/saasitone/ent"
"git.grosinger.net/tgrosinger/saasitone/ent/user"
"git.grosinger.net/tgrosinger/saasitone/pkg/context"
"git.grosinger.net/tgrosinger/saasitone/pkg/models"
)
// LoadUser loads the user based on the ID provided as a path parameter
func LoadUser(orm *ent.Client) echo.MiddlewareFunc {
func LoadUser(db *models.Client) echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
userID, err := strconv.Atoi(c.Param("user"))
@ -21,23 +21,20 @@ func LoadUser(orm *ent.Client) echo.MiddlewareFunc {
return echo.NewHTTPError(http.StatusNotFound)
}
u, err := orm.User.
Query().
Where(user.ID(userID)).
Only(c.Request().Context())
switch err.(type) {
case nil:
c.Set(context.UserKey, u)
u, err := db.C.GetUserByID(c.Request().Context(), userID)
if err == nil {
c.Set(context.UserKey, &u)
return next(c)
case *ent.NotFoundError:
return echo.NewHTTPError(http.StatusNotFound)
default:
return echo.NewHTTPError(
http.StatusInternalServerError,
fmt.Sprintf("error querying user: %v", err),
)
}
if err == sql.ErrNoRows {
return echo.NewHTTPError(http.StatusNotFound)
}
return echo.NewHTTPError(
http.StatusInternalServerError,
fmt.Sprintf("error querying user: %v", err),
)
}
}
}

View File

@ -7,17 +7,17 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"git.grosinger.net/tgrosinger/saasitone/ent"
"git.grosinger.net/tgrosinger/saasitone/pkg/context"
"git.grosinger.net/tgrosinger/saasitone/pkg/tests"
"git.grosinger.net/tgrosinger/saasitone/pkg/models/sqlc"
)
func TestLoadUser(t *testing.T) {
ctx, _ := tests.NewContext(c.Web, "/")
ctx.SetParamNames("user")
ctx.SetParamValues(fmt.Sprintf("%d", usr.ID))
_ = tests.ExecuteMiddleware(ctx, LoadUser(c.ORM))
ctxUsr, ok := ctx.Get(context.UserKey).(*ent.User)
_ = tests.ExecuteMiddleware(ctx, LoadUser(c.DB))
ctxUsr, ok := ctx.Get(context.UserKey).(*sqlc.User)
require.True(t, ok)
assert.Equal(t, usr.ID, ctxUsr.ID)
}

View File

@ -5,14 +5,14 @@ import (
"testing"
"git.grosinger.net/tgrosinger/saasitone/config"
"git.grosinger.net/tgrosinger/saasitone/ent"
"git.grosinger.net/tgrosinger/saasitone/pkg/models/sqlc"
"git.grosinger.net/tgrosinger/saasitone/pkg/services"
"git.grosinger.net/tgrosinger/saasitone/pkg/tests"
)
var (
c *services.Container
usr *ent.User
usr *sqlc.User
)
func TestMain(m *testing.M) {
@ -24,7 +24,7 @@ func TestMain(m *testing.M) {
// Create a user
var err error
if usr, err = tests.CreateUser(c.ORM); err != nil {
if usr, err = tests.CreateUser(c.DB); err != nil {
panic(err)
}

119
pkg/models/db.go Normal file
View File

@ -0,0 +1,119 @@
package models
import (
"database/sql"
"fmt"
"log/slog"
"github.com/golang-migrate/migrate/v4"
"github.com/golang-migrate/migrate/v4/database/sqlite3"
"github.com/golang-migrate/migrate/v4/source/file"
"git.grosinger.net/tgrosinger/saasitone/config"
"git.grosinger.net/tgrosinger/saasitone/pkg/models/sqlc"
)
// TODO: Move this into services and have DBClient and NewDBClient
type Client struct {
db *sql.DB
C *sqlc.Queries
User *UserClient
}
func New(cfg *config.Config) (*Client, error) {
logger := slog.Default()
dbFilepath := cfg.Storage.DatabaseFile
if cfg.App.Environment == config.EnvTest {
// In memory only
dbFilepath = ":memory:"
}
logger.Info("Opening database file",
"filepath", dbFilepath)
fn := fmt.Sprintf("file:%s?_fk=1&_journal=WAL&cache=shared&_busy_timeout=5000", dbFilepath)
db, err := sql.Open("sqlite3", fn)
if err != nil {
return nil, err
}
client := Client{
db: db,
C: sqlc.New(db),
}
client.User = &UserClient{db: db}
migrationsDirPath := cfg.Storage.MigrationsDir
logger.Info("Loading schema migrations",
"filepath", migrationsDirPath)
err = client.initSchema(migrationsDirPath)
if err != nil {
return nil, err
}
return &client, nil
}
// initSchema ensures that the database is current with the migrations contained
// in db/migrations.
func (c *Client) initSchema(migrationsDir string) error {
driver, err := sqlite3.WithInstance(c.db, &sqlite3.Config{})
if err != nil {
return err
}
fSrc, err := (&file.File{}).Open(migrationsDir)
if err != nil {
fmt.Println("Got here 2: " + migrationsDir)
return err
}
m, err := migrate.NewWithInstance("file", fSrc, "sqlite", driver)
if err != nil {
return err
}
err = m.Up()
if err == migrate.ErrNoChange {
return nil
}
return err
}
// WithTx executes the provided callback with access to a database transaction.
// If the callback returns an error the transaction will be rolled back.
func (c *Client) WithTx(fn func(tx *sql.Tx) error) error {
tx, err := c.db.Begin()
if err != nil {
return err
}
err = fn(tx)
if err != nil {
_ = tx.Rollback()
return err
}
return tx.Commit()
}
func (c *Client) WithSqlcTx(fn func(*sqlc.Queries) error) error {
return c.WithTx(
func(tx *sql.Tx) error {
return fn(c.C.WithTx(tx))
},
)
}
// DB returns the underlying database object. Avoid whenever possible and use
// either sqlc (preferred) or sub-clients.
func (c *Client) DB() *sql.DB {
return c.db
}
func (c *Client) Close() error {
return c.db.Close()
}

31
pkg/models/sqlc/db.go Normal file
View File

@ -0,0 +1,31 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.25.0
package sqlc
import (
"context"
"database/sql"
)
type DBTX interface {
ExecContext(context.Context, string, ...interface{}) (sql.Result, error)
PrepareContext(context.Context, string) (*sql.Stmt, error)
QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error)
QueryRowContext(context.Context, string, ...interface{}) *sql.Row
}
func New(db DBTX) *Queries {
return &Queries{db: db}
}
type Queries struct {
db DBTX
}
func (q *Queries) WithTx(tx *sql.Tx) *Queries {
return &Queries{
db: tx,
}
}

25
pkg/models/sqlc/models.go Normal file
View File

@ -0,0 +1,25 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.25.0
package sqlc
import (
"git.grosinger.net/tgrosinger/saasitone/pkg/db"
)
type PasswordToken struct {
ID int `db:"id"`
Hash string `db:"hash"`
CreatedAt db.Time `db:"created_at"`
PasswordTokenUser int `db:"password_token_user"`
}
type User struct {
ID int `db:"id"`
Name string `db:"name"`
Email string `db:"email"`
Password string `db:"password"`
Verified int `db:"verified"`
CreatedAt db.Time `db:"created_at"`
}

View File

@ -0,0 +1,126 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.25.0
// source: password_tokens.sql
package sqlc
import (
"context"
"git.grosinger.net/tgrosinger/saasitone/pkg/db"
)
const createPasswordToken = `-- name: CreatePasswordToken :one
INSERT INTO password_tokens (
hash, password_token_user
) VALUES (
?, ?
) RETURNING id, hash, created_at, password_token_user
`
type CreatePasswordTokenParams struct {
Hash string `db:"hash"`
PasswordTokenUser int `db:"password_token_user"`
}
func (q *Queries) CreatePasswordToken(ctx context.Context, arg CreatePasswordTokenParams) (PasswordToken, error) {
row := q.db.QueryRowContext(ctx, createPasswordToken, arg.Hash, arg.PasswordTokenUser)
var i PasswordToken
err := row.Scan(
&i.ID,
&i.Hash,
&i.CreatedAt,
&i.PasswordTokenUser,
)
return i, err
}
const deletePasswordTokens = `-- name: DeletePasswordTokens :exec
DELETE FROM password_tokens
WHERE password_token_user = ?
`
func (q *Queries) DeletePasswordTokens(ctx context.Context, passwordTokenUser int) error {
_, err := q.db.ExecContext(ctx, deletePasswordTokens, passwordTokenUser)
return err
}
const getAllPasswordTokensForUser = `-- name: GetAllPasswordTokensForUser :many
SELECT id, hash, created_at, password_token_user FROM password_tokens
WHERE password_token_user = ?
`
// GetAllPasswordTokensForUser retrieves all password tokens without checking expiration.
func (q *Queries) GetAllPasswordTokensForUser(ctx context.Context, passwordTokenUser int) ([]PasswordToken, error) {
rows, err := q.db.QueryContext(ctx, getAllPasswordTokensForUser, passwordTokenUser)
if err != nil {
return nil, err
}
defer rows.Close()
var items []PasswordToken
for rows.Next() {
var i PasswordToken
if err := rows.Scan(
&i.ID,
&i.Hash,
&i.CreatedAt,
&i.PasswordTokenUser,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getValidPasswordToken = `-- name: GetValidPasswordToken :one
SELECT id, hash, created_at, password_token_user FROM password_tokens
WHERE
id = ?
AND password_token_user = ?
AND datetime(created_at) > datetime(?)
LIMIT 1
`
type GetValidPasswordTokenParams struct {
ID int `db:"id"`
PasswordTokenUser int `db:"password_token_user"`
Datetime interface{} `db:"datetime"`
}
// GetValidPasswordToken returns only valid password tokens for the provided
// user, and only if the created_at time is greater than the provided time.
func (q *Queries) GetValidPasswordToken(ctx context.Context, arg GetValidPasswordTokenParams) (PasswordToken, error) {
row := q.db.QueryRowContext(ctx, getValidPasswordToken, arg.ID, arg.PasswordTokenUser, arg.Datetime)
var i PasswordToken
err := row.Scan(
&i.ID,
&i.Hash,
&i.CreatedAt,
&i.PasswordTokenUser,
)
return i, err
}
const updatePasswordTokenCreatedAt = `-- name: UpdatePasswordTokenCreatedAt :exec
UPDATE password_tokens
SET created_at = ?
WHERE id = ?
`
type UpdatePasswordTokenCreatedAtParams struct {
CreatedAt db.Time `db:"created_at"`
ID int `db:"id"`
}
func (q *Queries) UpdatePasswordTokenCreatedAt(ctx context.Context, arg UpdatePasswordTokenCreatedAtParams) error {
_, err := q.db.ExecContext(ctx, updatePasswordTokenCreatedAt, arg.CreatedAt, arg.ID)
return err
}

View File

@ -0,0 +1,105 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.25.0
// source: users.sql
package sqlc
import (
"context"
)
const createUser = `-- name: CreateUser :one
INSERT INTO users (
name, email, password
) VALUES (
?, ?, ?
) RETURNING id, name, email, password, verified, created_at
`
type CreateUserParams struct {
Name string `db:"name"`
Email string `db:"email"`
Password string `db:"password"`
}
func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (User, error) {
row := q.db.QueryRowContext(ctx, createUser, arg.Name, arg.Email, arg.Password)
var i User
err := row.Scan(
&i.ID,
&i.Name,
&i.Email,
&i.Password,
&i.Verified,
&i.CreatedAt,
)
return i, err
}
const getUserByEmail = `-- name: GetUserByEmail :one
SELECT id, name, email, password, verified, created_at FROM users
WHERE email = lower(?)
LIMIT 1
`
func (q *Queries) GetUserByEmail(ctx context.Context, lower string) (User, error) {
row := q.db.QueryRowContext(ctx, getUserByEmail, lower)
var i User
err := row.Scan(
&i.ID,
&i.Name,
&i.Email,
&i.Password,
&i.Verified,
&i.CreatedAt,
)
return i, err
}
const getUserByID = `-- name: GetUserByID :one
SELECT id, name, email, password, verified, created_at FROM users
WHERE id = ?
LIMIT 1
`
func (q *Queries) GetUserByID(ctx context.Context, id int) (User, error) {
row := q.db.QueryRowContext(ctx, getUserByID, id)
var i User
err := row.Scan(
&i.ID,
&i.Name,
&i.Email,
&i.Password,
&i.Verified,
&i.CreatedAt,
)
return i, err
}
const updateUserPassword = `-- name: UpdateUserPassword :exec
UPDATE users
SET password = ?
WHERE id = ?
`
type UpdateUserPasswordParams struct {
Password string `db:"password"`
ID int `db:"id"`
}
func (q *Queries) UpdateUserPassword(ctx context.Context, arg UpdateUserPasswordParams) error {
_, err := q.db.ExecContext(ctx, updateUserPassword, arg.Password, arg.ID)
return err
}
const updateUserSetVerified = `-- name: UpdateUserSetVerified :exec
UPDATE users
SET verified = 1
WHERE email = ?
`
func (q *Queries) UpdateUserSetVerified(ctx context.Context, email string) error {
_, err := q.db.ExecContext(ctx, updateUserSetVerified, email)
return err
}

9
pkg/models/users.go Normal file
View File

@ -0,0 +1,9 @@
package models
import "database/sql"
// UserClient is a struct that can be used to create custom methods for
// interacting with users in the database.
type UserClient struct {
db *sql.DB
}

View File

@ -8,9 +8,9 @@ import (
"github.com/labstack/echo/v4"
echomw "github.com/labstack/echo/v4/middleware"
"git.grosinger.net/tgrosinger/saasitone/ent"
"git.grosinger.net/tgrosinger/saasitone/pkg/context"
"git.grosinger.net/tgrosinger/saasitone/pkg/htmx"
"git.grosinger.net/tgrosinger/saasitone/pkg/models/sqlc"
"git.grosinger.net/tgrosinger/saasitone/pkg/msg"
"git.grosinger.net/tgrosinger/saasitone/templates"
)
@ -67,7 +67,7 @@ type Page struct {
IsAuth bool
// AuthUser stores the authenticated user
AuthUser *ent.User
AuthUser *sqlc.User
// StatusCode stores the HTTP status code that will be returned
StatusCode int
@ -141,7 +141,7 @@ func New(ctx echo.Context) Page {
if u := ctx.Get(context.AuthenticatedUserKey); u != nil {
p.IsAuth = true
p.AuthUser = u.(*ent.User)
p.AuthUser = u.(*sqlc.User)
}
p.HTMX.Request = htmx.GetRequest(ctx)

View File

@ -8,8 +8,8 @@ import (
echomw "github.com/labstack/echo/v4/middleware"
"github.com/stretchr/testify/assert"
"git.grosinger.net/tgrosinger/saasitone/ent"
"git.grosinger.net/tgrosinger/saasitone/pkg/context"
"git.grosinger.net/tgrosinger/saasitone/pkg/models/sqlc"
"git.grosinger.net/tgrosinger/saasitone/pkg/msg"
"git.grosinger.net/tgrosinger/saasitone/pkg/tests"
)
@ -31,7 +31,7 @@ func TestNew(t *testing.T) {
assert.False(t, p.Cache.Enabled)
ctx, _ = tests.NewContext(e, "/abc?def=123")
usr := &ent.User{
usr := &sqlc.User{
ID: 1,
}
ctx.Set(context.AuthenticatedUserKey, usr)

View File

@ -2,6 +2,7 @@ package services
import (
"crypto/rand"
"database/sql"
"encoding/hex"
"errors"
"fmt"
@ -12,10 +13,8 @@ import (
"golang.org/x/crypto/bcrypt"
"git.grosinger.net/tgrosinger/saasitone/config"
"git.grosinger.net/tgrosinger/saasitone/ent"
"git.grosinger.net/tgrosinger/saasitone/ent/passwordtoken"
"git.grosinger.net/tgrosinger/saasitone/ent/user"
"git.grosinger.net/tgrosinger/saasitone/pkg/context"
"git.grosinger.net/tgrosinger/saasitone/pkg/models"
"git.grosinger.net/tgrosinger/saasitone/pkg/models/sqlc"
"git.grosinger.net/tgrosinger/saasitone/pkg/session"
)
@ -49,14 +48,14 @@ func (e InvalidPasswordTokenError) Error() string {
// AuthClient is the client that handles authentication requests
type AuthClient struct {
config *config.Config
orm *ent.Client
db *models.Client
}
// NewAuthClient creates a new authentication client
func NewAuthClient(cfg *config.Config, orm *ent.Client) *AuthClient {
func NewAuthClient(cfg *config.Config, db *models.Client) *AuthClient {
return &AuthClient{
config: cfg,
orm: orm,
db: db,
}
}
@ -96,11 +95,13 @@ func (c *AuthClient) GetAuthenticatedUserID(ctx echo.Context) (int, error) {
}
// GetAuthenticatedUser returns the authenticated user if the user is logged in
func (c *AuthClient) GetAuthenticatedUser(ctx echo.Context) (*ent.User, error) {
func (c *AuthClient) GetAuthenticatedUser(ctx echo.Context) (*sqlc.User, error) {
if userID, err := c.GetAuthenticatedUserID(ctx); err == nil {
return c.orm.User.Query().
Where(user.ID(userID)).
Only(ctx.Request().Context())
u, err := c.db.C.GetUserByID(ctx.Request().Context(), userID)
if err != nil {
return nil, err
}
return &u, nil
}
return nil, NotAuthenticatedError{}
@ -124,25 +125,24 @@ func (c *AuthClient) CheckPassword(password, hash string) error {
// For security purposes, the token itself is not stored in the database but rather
// a hash of the token, exactly how passwords are handled. This method returns both
// the generated token as well as the token entity which only contains the hash.
func (c *AuthClient) GeneratePasswordResetToken(ctx echo.Context, userID int) (string, *ent.PasswordToken, error) {
func (c *AuthClient) GeneratePasswordResetToken(ctx echo.Context, userID int) (string, sqlc.PasswordToken, error) {
// Generate the token, which is what will go in the URL, but not the database
token, err := c.RandomToken(c.config.App.PasswordToken.Length)
if err != nil {
return "", nil, err
return "", sqlc.PasswordToken{}, err
}
// Hash the token, which is what will be stored in the database
hash, err := c.HashPassword(token)
if err != nil {
return "", nil, err
return "", sqlc.PasswordToken{}, err
}
// Create and save the password reset token
pt, err := c.orm.PasswordToken.
Create().
SetHash(hash).
SetUserID(userID).
Save(ctx.Request().Context())
pt, err := c.db.C.CreatePasswordToken(ctx.Request().Context(), sqlc.CreatePasswordTokenParams{
Hash: hash,
PasswordTokenUser: userID,
})
return token, pt, err
}
@ -150,43 +150,35 @@ func (c *AuthClient) GeneratePasswordResetToken(ctx echo.Context, userID int) (s
// GetValidPasswordToken returns a valid, non-expired password token entity for a given user, token ID and token.
// Since the actual token is not stored in the database for security purposes, if a matching password token entity is
// found a hash of the provided token is compared with the hash stored in the database in order to validate.
func (c *AuthClient) GetValidPasswordToken(ctx echo.Context, userID, tokenID int, token string) (*ent.PasswordToken, error) {
func (c *AuthClient) GetValidPasswordToken(ctx echo.Context, userID, tokenID int, token string) (*sqlc.PasswordToken, error) {
// Ensure expired tokens are never returned
expiration := time.Now().Add(-c.config.App.PasswordToken.Expiration)
// Query to find a password token entity that matches the given user and token ID
pt, err := c.orm.PasswordToken.
Query().
Where(passwordtoken.ID(tokenID)).
Where(passwordtoken.HasUserWith(user.ID(userID))).
Where(passwordtoken.CreatedAtGTE(expiration)).
Only(ctx.Request().Context())
pt, err := c.db.C.GetValidPasswordToken(ctx.Request().Context(),
sqlc.GetValidPasswordTokenParams{
ID: tokenID,
PasswordTokenUser: userID,
Datetime: expiration,
})
switch err.(type) {
case *ent.NotFoundError:
case nil:
// Check the token for a hash match
if err := c.CheckPassword(token, pt.Hash); err == nil {
return pt, nil
}
default:
if !context.IsCanceledError(err) {
return nil, err
}
if err == sql.ErrNoRows {
return nil, InvalidPasswordTokenError{}
} else if err != nil {
return nil, err
}
// Check the token for a hash match
if err := c.CheckPassword(token, pt.Hash); err == nil {
return &pt, nil
}
return nil, InvalidPasswordTokenError{}
}
// DeletePasswordTokens deletes all password tokens in the database for a belonging to a given user.
// This should be called after a successful password reset.
func (c *AuthClient) DeletePasswordTokens(ctx echo.Context, userID int) error {
_, err := c.orm.PasswordToken.
Delete().
Where(passwordtoken.HasUserWith(user.ID(userID))).
Exec(ctx.Request().Context())
return err
return c.db.C.DeletePasswordTokens(ctx.Request().Context(), userID)
}
// RandomToken generates a random token string of a given length

View File

@ -9,8 +9,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"git.grosinger.net/tgrosinger/saasitone/ent/passwordtoken"
"git.grosinger.net/tgrosinger/saasitone/ent/user"
"git.grosinger.net/tgrosinger/saasitone/pkg/models/sqlc"
"git.grosinger.net/tgrosinger/saasitone/pkg/db"
)
func TestAuthClient_Auth(t *testing.T) {
@ -69,13 +69,11 @@ func TestAuthClient_GetValidPasswordToken(t *testing.T) {
assert.Equal(t, pt.ID, pt2.ID)
// Expire the token by pushing the date far enough back
count, err := c.ORM.PasswordToken.
Update().
SetCreatedAt(time.Now().Add(-(c.Config.App.PasswordToken.Expiration + time.Hour))).
Where(passwordtoken.ID(pt.ID)).
Save(context.Background())
err = c.DB.C.UpdatePasswordTokenCreatedAt(context.Background(), sqlc.UpdatePasswordTokenCreatedAtParams{
CreatedAt: db.Time{Time: time.Now().Add(-(c.Config.App.PasswordToken.Expiration + time.Hour))},
ID: pt.ID,
})
require.NoError(t, err)
require.Equal(t, 1, count)
// Expired tokens should not be valid
_, err = c.Auth.GetValidPasswordToken(ctx, usr.ID, pt.ID, token)
@ -94,13 +92,9 @@ func TestAuthClient_DeletePasswordTokens(t *testing.T) {
require.NoError(t, err)
// Check that no tokens remain
count, err := c.ORM.PasswordToken.
Query().
Where(passwordtoken.HasUserWith(user.ID(usr.ID))).
Count(context.Background())
tokens, err := c.DB.C.GetAllPasswordTokensForUser(context.Background(), usr.ID)
require.NoError(t, err)
assert.Equal(t, 0, count)
assert.Len(t, tokens, 0)
}
func TestAuthClient_RandomToken(t *testing.T) {

View File

@ -1,21 +1,15 @@
package services
import (
"context"
"database/sql"
"fmt"
"log/slog"
"os"
"strings"
entsql "entgo.io/ent/dialect/sql"
"github.com/labstack/echo/v4"
_ "github.com/mattn/go-sqlite3"
"git.grosinger.net/tgrosinger/saasitone/config"
"git.grosinger.net/tgrosinger/saasitone/ent"
_ "git.grosinger.net/tgrosinger/saasitone/ent/runtime" // Require by ent
"git.grosinger.net/tgrosinger/saasitone/pkg/funcmap"
"git.grosinger.net/tgrosinger/saasitone/pkg/models"
)
// Container contains all services used by the application and provides an easy way to handle dependency
@ -33,11 +27,8 @@ type Container struct {
// Cache contains the cache client
Cache *CacheClient
// Database stores the connection to the database
Database *sql.DB
// ORM stores a client to the ORM
ORM *ent.Client
// DB is the connection to the database and models for interacting with it
DB *models.Client
// Mail stores an email sending client
Mail *MailClient
@ -60,7 +51,6 @@ func NewContainer() *Container {
c.initWeb()
c.initCache()
c.initDatabase()
c.initORM()
c.initAuth()
c.initTemplateRenderer()
c.initMail()
@ -71,10 +61,7 @@ func NewContainer() *Container {
// Shutdown shuts the Container down and disconnects all connections.
// If the task runner was started, cancel the context to shut it down prior to calling this.
func (c *Container) Shutdown() error {
if err := c.ORM.Close(); err != nil {
return err
}
if err := c.Database.Close(); err != nil {
if err := c.DB.Close(); err != nil {
return err
}
c.Cache.Close()
@ -123,37 +110,17 @@ func (c *Container) initCache() {
// initDatabase initializes the database
func (c *Container) initDatabase() {
var err error
var connection string
switch c.Config.App.Environment {
case config.EnvTest:
// TODO: Drop/recreate the DB, if this isn't in memory?
connection = c.Config.Database.TestConnection
default:
connection = c.Config.Database.Connection
}
c.Database, err = openDB(c.Config.Database.Driver, connection)
client, err := models.New(c.Config)
if err != nil {
panic(err)
}
}
// initORM initializes the ORM
func (c *Container) initORM() {
drv := entsql.OpenDB(c.Config.Database.Driver, c.Database)
c.ORM = ent.NewClient(ent.Driver(drv))
// Run the auto migration tool.
if err := c.ORM.Schema.Create(context.Background()); err != nil {
panic(err)
}
c.DB = client
}
// initAuth initializes the authentication client
func (c *Container) initAuth() {
c.Auth = NewAuthClient(c.Config, c.ORM)
c.Auth = NewAuthClient(c.Config, c.DB)
}
// initTemplateRenderer initializes the template renderer
@ -175,27 +142,8 @@ func (c *Container) initTasks() {
var err error
// You could use a separate database for tasks, if you'd like. but using one
// makes transaction support easier
c.Tasks, err = NewTaskClient(c.Config.Tasks, c.Database)
c.Tasks, err = NewTaskClient(c.Config.Tasks, c.DB.DB())
if err != nil {
panic(fmt.Sprintf("failed to create task client: %v", err))
}
}
// openDB opens a database connection
func openDB(driver, connection string) (*sql.DB, error) {
// Helper to automatically create the directories that the specified sqlite file
// should reside in, if one
if driver == "sqlite3" {
d := strings.Split(connection, "/")
if len(d) > 1 {
path := strings.Join(d[:len(d)-1], "/")
if err := os.MkdirAll(path, 0755); err != nil {
return nil, err
}
}
}
return sql.Open(driver, connection)
}

View File

@ -11,8 +11,7 @@ func TestNewContainer(t *testing.T) {
assert.NotNil(t, c.Config)
assert.NotNil(t, c.Validator)
assert.NotNil(t, c.Cache)
assert.NotNil(t, c.Database)
assert.NotNil(t, c.ORM)
assert.NotNil(t, c.DB)
assert.NotNil(t, c.Mail)
assert.NotNil(t, c.Auth)
assert.NotNil(t, c.TemplateRenderer)

View File

@ -7,14 +7,14 @@ import (
"github.com/labstack/echo/v4"
"git.grosinger.net/tgrosinger/saasitone/config"
"git.grosinger.net/tgrosinger/saasitone/ent"
"git.grosinger.net/tgrosinger/saasitone/pkg/models/sqlc"
"git.grosinger.net/tgrosinger/saasitone/pkg/tests"
)
var (
c *Container
ctx echo.Context
usr *ent.User
usr *sqlc.User
)
func TestMain(m *testing.M) {
@ -30,7 +30,7 @@ func TestMain(m *testing.M) {
// Create a test user
var err error
if usr, err = tests.CreateUser(c.ORM); err != nil {
if usr, err = tests.CreateUser(c.DB); err != nil {
panic(err)
}

View File

@ -16,7 +16,8 @@ import (
"github.com/gorilla/sessions"
"github.com/labstack/echo/v4"
"git.grosinger.net/tgrosinger/saasitone/ent"
"git.grosinger.net/tgrosinger/saasitone/pkg/models"
"git.grosinger.net/tgrosinger/saasitone/pkg/models/sqlc"
"git.grosinger.net/tgrosinger/saasitone/pkg/session"
)
@ -63,12 +64,17 @@ func AssertHTTPErrorCode(t *testing.T, err error, code int) {
}
// CreateUser creates a random user entity
func CreateUser(orm *ent.Client) (*ent.User, error) {
func CreateUser(db *models.Client) (*sqlc.User, error) {
seed := fmt.Sprintf("%d-%d", time.Now().UnixMilli(), rand.Intn(1000000))
return orm.User.
Create().
SetEmail(fmt.Sprintf("testuser-%s@localhost.localhost", seed)).
SetPassword("password").
SetName(fmt.Sprintf("Test User %s", seed)).
Save(context.Background())
usr, err := db.C.CreateUser(context.Background(), sqlc.CreateUserParams{
Name: fmt.Sprintf("Test User %s", seed),
Email: fmt.Sprintf("testuser-%s@localhost.localhost", seed),
Password: "password",
})
if err != nil {
return nil, err
}
return &usr, nil
}

29
sqlc.yaml Normal file
View File

@ -0,0 +1,29 @@
version: "2"
sql:
- engine: "sqlite"
schema: "db/migrations"
queries: "db/queries"
gen:
go:
out: "pkg/models/sqlc"
emit_db_tags: true
overrides:
go:
overrides:
- db_type: "integer"
go_type:
type: "int"
- db_type: "integer"
go_type:
type: "NullInt"
import: "git.grosinger.net/tgrosinger/sassitone/pkg/conv"
nullable: true
- column: "main.password_tokens.created_at"
go_type:
type: "Time"
import: "git.grosinger.net/tgrosinger/saasitone/pkg/db"
- column: "main.users.created_at"
go_type:
type: "Time"
import: "git.grosinger.net/tgrosinger/saasitone/pkg/db"