refactor!: working WD-4 user discovery

This commit is contained in:
DevMiner 2024-08-20 22:43:26 +02:00
parent cf0053312d
commit 61891d891a
91 changed files with 12768 additions and 5562 deletions

8
.dockerignore Normal file
View file

@ -0,0 +1,8 @@
*.pem
*.db
.env*
node_modules
compose.yml
Dockerfile
.dockerignore
.gitignore

21
.env
View file

@ -1,14 +1,17 @@
PUBLIC_ADDRESS="https://localhost"
INSTANCE_NAME="lysand-test"
INSTANCE_DESCRIPTION="Versia-Go Instance"
PORT=8443
NATS_URI="nats://localhost:4222"
PUBLIC_ADDRESS=https://localhost
INSTANCE_NAME=lysand-test
INSTANCE_DESCRIPTION=Versia-Go Instance
NATS_URI=nats://localhost:4222
NATS_STREAM_NAME=versia-go
# SQLite
DATABASE_URI="file:./versia-go.db?cache=shared&_fk=1"
DATABASE_URI=file:./versia-go.db?cache=shared&_fk=1
# PostgreSQL
# DATABASE_URI="postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable"
# DATABASE_URI=postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable
ENVIRONMENT="development"
OTLP_ENDPOINT=""
SENTRY_DSN=""
ENVIRONMENT=development
OTLP_ENDPOINT=
SENTRY_DSN=

5
.gitignore vendored
View file

@ -1,4 +1,5 @@
cert.pem
key.pem
*.pem
*.crt
*.db
.env.*
node_modules

24
Dockerfile Normal file
View file

@ -0,0 +1,24 @@
FROM golang:1.23-alpine AS builder
WORKDIR /build
COPY ./go.mod .
COPY ./go.sum .
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /build/versia-go
FROM alpine:3 AS runner
WORKDIR /app
RUN apk add curl --no-cache
# Copy over some sources to get Sentry's source mapping working in Go
# https://docs.sentry.io/platforms/go/troubleshooting/#missing-stack-trace
COPY ./pkg /app/pkg
COPY ./internal /app/internal
COPY ./ent app/ent
COPY --from=builder /build/versia-go /usr/local/bin/versia-go
ENTRYPOINT [ "/usr/local/bin/versia-go" ]

View file

@ -1,12 +1,18 @@
x-versia: &versia-default
build: .
env_file: [ .env, .env.local ]
depends_on:
- nats
services:
db:
image: postgres:16.2-alpine
environment:
POSTGRES_DB: postgres
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports:
- "5432:5432"
# db:
# image: postgres:16.2-alpine
# environment:
# POSTGRES_DB: postgres
# POSTGRES_USER: postgres
# POSTGRES_PASSWORD: postgres
# ports:
# - "5432:5432"
nats:
image: nats:2.9.25-scratch
@ -14,3 +20,49 @@ services:
- "4222:4222"
- "8222:8222"
command: "--js"
versia-1:
<<: *versia-default
hostname: lysand-test.i.devminer.xyz
volumes:
- /etc/ssl/certs:/etc/ssl/certs:ro
- /etc/ca-certificates/extracted:/etc/ca-certificates/extracted
- type: bind
source: ./key.pem
target: /app/key.pem
- type: bind
source: ./cert.pem
target: /app/cert.pem
- type: bind
source: ./1.db
target: /app/test.db
environment:
PORT: 8443
NATS_URI: nats://nats:4222
PUBLIC_ADDRESS: https://lysand-test.i.devminer.xyz:8443
NATS_STREAM_NAME: versia-go-1
ports:
- "8443:8443"
versia-2:
<<: *versia-default
hostname: lysand-test-2.i.devminer.xyz
volumes:
- /etc/ssl/certs:/etc/ssl/certs:ro
- /etc/ca-certificates/extracted:/etc/ca-certificates/extracted
- type: bind
source: ./key2.pem
target: /app/key.pem
- type: bind
source: ./cert2.pem
target: /app/cert.pem
- type: bind
source: ./2.db
target: /app/test.db
environment:
PORT: 8444
NATS_URI: nats://nats:4222
PUBLIC_ADDRESS: https://lysand-test-2.i.devminer.xyz:8444
NATS_STREAM_NAME: versia-go-2
ports:
- "8444:8444"

View file

@ -3,6 +3,7 @@ package config
import (
"net/url"
"os"
"strconv"
"git.devminer.xyz/devminer/unitel"
"github.com/joho/godotenv"
@ -10,11 +11,18 @@ import (
)
type Config struct {
PublicAddress *url.URL
Port int
PublicAddress *url.URL
Host string
SharedInboxURL *url.URL
InstanceName string
InstanceDescription *string
NATSURI string
NATSURI string
NATSStreamName string
DatabaseURI string
Telemetry unitel.Opts
@ -33,12 +41,18 @@ func Load() {
}
C = Config{
PublicAddress: publicAddress,
Port: getEnvInt("PORT", 80),
PublicAddress: publicAddress,
Host: publicAddress.Host,
SharedInboxURL: publicAddress.ResolveReference(&url.URL{Path: "/api/inbox"}),
InstanceName: os.Getenv("INSTANCE_NAME"),
InstanceDescription: optionalEnvStr("INSTANCE_DESCRIPTION"),
NATSURI: os.Getenv("NATS_URI"),
DatabaseURI: os.Getenv("DATABASE_URI"),
NATSURI: os.Getenv("NATS_URI"),
NATSStreamName: getEnvStr("NATS_STREAM_NAME", "versia-go"),
DatabaseURI: os.Getenv("DATABASE_URI"),
Telemetry: unitel.ParseOpts("versia-go"),
}
@ -53,3 +67,24 @@ func optionalEnvStr(key string) *string {
}
return &value
}
func getEnvStr(key, default_ string) string {
if value, ok := os.LookupEnv(key); ok {
return value
}
return default_
}
func getEnvInt(key string, default_ int) int {
if value, ok := os.LookupEnv(key); ok {
parsed, err := strconv.Atoi(value)
if err != nil {
panic(err)
}
return parsed
}
return default_
}

View file

@ -19,8 +19,8 @@ import (
"github.com/lysand-org/versia-go/ent/attachment"
"github.com/lysand-org/versia-go/ent/follow"
"github.com/lysand-org/versia-go/ent/image"
"github.com/lysand-org/versia-go/ent/instancemetadata"
"github.com/lysand-org/versia-go/ent/note"
"github.com/lysand-org/versia-go/ent/servermetadata"
"github.com/lysand-org/versia-go/ent/user"
)
@ -35,10 +35,10 @@ type Client struct {
Follow *FollowClient
// Image is the client for interacting with the Image builders.
Image *ImageClient
// InstanceMetadata is the client for interacting with the InstanceMetadata builders.
InstanceMetadata *InstanceMetadataClient
// Note is the client for interacting with the Note builders.
Note *NoteClient
// ServerMetadata is the client for interacting with the ServerMetadata builders.
ServerMetadata *ServerMetadataClient
// User is the client for interacting with the User builders.
User *UserClient
}
@ -55,8 +55,8 @@ func (c *Client) init() {
c.Attachment = NewAttachmentClient(c.config)
c.Follow = NewFollowClient(c.config)
c.Image = NewImageClient(c.config)
c.InstanceMetadata = NewInstanceMetadataClient(c.config)
c.Note = NewNoteClient(c.config)
c.ServerMetadata = NewServerMetadataClient(c.config)
c.User = NewUserClient(c.config)
}
@ -148,14 +148,14 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) {
cfg := c.config
cfg.driver = tx
return &Tx{
ctx: ctx,
config: cfg,
Attachment: NewAttachmentClient(cfg),
Follow: NewFollowClient(cfg),
Image: NewImageClient(cfg),
Note: NewNoteClient(cfg),
ServerMetadata: NewServerMetadataClient(cfg),
User: NewUserClient(cfg),
ctx: ctx,
config: cfg,
Attachment: NewAttachmentClient(cfg),
Follow: NewFollowClient(cfg),
Image: NewImageClient(cfg),
InstanceMetadata: NewInstanceMetadataClient(cfg),
Note: NewNoteClient(cfg),
User: NewUserClient(cfg),
}, nil
}
@ -173,14 +173,14 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error)
cfg := c.config
cfg.driver = &txDriver{tx: tx, drv: c.driver}
return &Tx{
ctx: ctx,
config: cfg,
Attachment: NewAttachmentClient(cfg),
Follow: NewFollowClient(cfg),
Image: NewImageClient(cfg),
Note: NewNoteClient(cfg),
ServerMetadata: NewServerMetadataClient(cfg),
User: NewUserClient(cfg),
ctx: ctx,
config: cfg,
Attachment: NewAttachmentClient(cfg),
Follow: NewFollowClient(cfg),
Image: NewImageClient(cfg),
InstanceMetadata: NewInstanceMetadataClient(cfg),
Note: NewNoteClient(cfg),
User: NewUserClient(cfg),
}, nil
}
@ -210,7 +210,7 @@ func (c *Client) Close() error {
// In order to add hooks to a specific client, call: `client.Node.Use(...)`.
func (c *Client) Use(hooks ...Hook) {
for _, n := range []interface{ Use(...Hook) }{
c.Attachment, c.Follow, c.Image, c.Note, c.ServerMetadata, c.User,
c.Attachment, c.Follow, c.Image, c.InstanceMetadata, c.Note, c.User,
} {
n.Use(hooks...)
}
@ -220,7 +220,7 @@ func (c *Client) Use(hooks ...Hook) {
// In order to add interceptors to a specific client, call: `client.Node.Intercept(...)`.
func (c *Client) Intercept(interceptors ...Interceptor) {
for _, n := range []interface{ Intercept(...Interceptor) }{
c.Attachment, c.Follow, c.Image, c.Note, c.ServerMetadata, c.User,
c.Attachment, c.Follow, c.Image, c.InstanceMetadata, c.Note, c.User,
} {
n.Intercept(interceptors...)
}
@ -235,10 +235,10 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) {
return c.Follow.mutate(ctx, m)
case *ImageMutation:
return c.Image.mutate(ctx, m)
case *InstanceMetadataMutation:
return c.InstanceMetadata.mutate(ctx, m)
case *NoteMutation:
return c.Note.mutate(ctx, m)
case *ServerMetadataMutation:
return c.ServerMetadata.mutate(ctx, m)
case *UserMutation:
return c.User.mutate(ctx, m)
default:
@ -693,6 +693,187 @@ func (c *ImageClient) mutate(ctx context.Context, m *ImageMutation) (Value, erro
}
}
// InstanceMetadataClient is a client for the InstanceMetadata schema.
type InstanceMetadataClient struct {
config
}
// NewInstanceMetadataClient returns a client for the InstanceMetadata from the given config.
func NewInstanceMetadataClient(c config) *InstanceMetadataClient {
return &InstanceMetadataClient{config: c}
}
// Use adds a list of mutation hooks to the hooks stack.
// A call to `Use(f, g, h)` equals to `instancemetadata.Hooks(f(g(h())))`.
func (c *InstanceMetadataClient) Use(hooks ...Hook) {
c.hooks.InstanceMetadata = append(c.hooks.InstanceMetadata, hooks...)
}
// Intercept adds a list of query interceptors to the interceptors stack.
// A call to `Intercept(f, g, h)` equals to `instancemetadata.Intercept(f(g(h())))`.
func (c *InstanceMetadataClient) Intercept(interceptors ...Interceptor) {
c.inters.InstanceMetadata = append(c.inters.InstanceMetadata, interceptors...)
}
// Create returns a builder for creating a InstanceMetadata entity.
func (c *InstanceMetadataClient) Create() *InstanceMetadataCreate {
mutation := newInstanceMetadataMutation(c.config, OpCreate)
return &InstanceMetadataCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// CreateBulk returns a builder for creating a bulk of InstanceMetadata entities.
func (c *InstanceMetadataClient) CreateBulk(builders ...*InstanceMetadataCreate) *InstanceMetadataCreateBulk {
return &InstanceMetadataCreateBulk{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 *InstanceMetadataClient) MapCreateBulk(slice any, setFunc func(*InstanceMetadataCreate, int)) *InstanceMetadataCreateBulk {
rv := reflect.ValueOf(slice)
if rv.Kind() != reflect.Slice {
return &InstanceMetadataCreateBulk{err: fmt.Errorf("calling to InstanceMetadataClient.MapCreateBulk with wrong type %T, need slice", slice)}
}
builders := make([]*InstanceMetadataCreate, rv.Len())
for i := 0; i < rv.Len(); i++ {
builders[i] = c.Create()
setFunc(builders[i], i)
}
return &InstanceMetadataCreateBulk{config: c.config, builders: builders}
}
// Update returns an update builder for InstanceMetadata.
func (c *InstanceMetadataClient) Update() *InstanceMetadataUpdate {
mutation := newInstanceMetadataMutation(c.config, OpUpdate)
return &InstanceMetadataUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOne returns an update builder for the given entity.
func (c *InstanceMetadataClient) UpdateOne(im *InstanceMetadata) *InstanceMetadataUpdateOne {
mutation := newInstanceMetadataMutation(c.config, OpUpdateOne, withInstanceMetadata(im))
return &InstanceMetadataUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOneID returns an update builder for the given id.
func (c *InstanceMetadataClient) UpdateOneID(id uuid.UUID) *InstanceMetadataUpdateOne {
mutation := newInstanceMetadataMutation(c.config, OpUpdateOne, withInstanceMetadataID(id))
return &InstanceMetadataUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// Delete returns a delete builder for InstanceMetadata.
func (c *InstanceMetadataClient) Delete() *InstanceMetadataDelete {
mutation := newInstanceMetadataMutation(c.config, OpDelete)
return &InstanceMetadataDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// DeleteOne returns a builder for deleting the given entity.
func (c *InstanceMetadataClient) DeleteOne(im *InstanceMetadata) *InstanceMetadataDeleteOne {
return c.DeleteOneID(im.ID)
}
// DeleteOneID returns a builder for deleting the given entity by its id.
func (c *InstanceMetadataClient) DeleteOneID(id uuid.UUID) *InstanceMetadataDeleteOne {
builder := c.Delete().Where(instancemetadata.ID(id))
builder.mutation.id = &id
builder.mutation.op = OpDeleteOne
return &InstanceMetadataDeleteOne{builder}
}
// Query returns a query builder for InstanceMetadata.
func (c *InstanceMetadataClient) Query() *InstanceMetadataQuery {
return &InstanceMetadataQuery{
config: c.config,
ctx: &QueryContext{Type: TypeInstanceMetadata},
inters: c.Interceptors(),
}
}
// Get returns a InstanceMetadata entity by its id.
func (c *InstanceMetadataClient) Get(ctx context.Context, id uuid.UUID) (*InstanceMetadata, error) {
return c.Query().Where(instancemetadata.ID(id)).Only(ctx)
}
// GetX is like Get, but panics if an error occurs.
func (c *InstanceMetadataClient) GetX(ctx context.Context, id uuid.UUID) *InstanceMetadata {
obj, err := c.Get(ctx, id)
if err != nil {
panic(err)
}
return obj
}
// QueryUsers queries the users edge of a InstanceMetadata.
func (c *InstanceMetadataClient) QueryUsers(im *InstanceMetadata) *UserQuery {
query := (&UserClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := im.ID
step := sqlgraph.NewStep(
sqlgraph.From(instancemetadata.Table, instancemetadata.FieldID, id),
sqlgraph.To(user.Table, user.FieldID),
sqlgraph.Edge(sqlgraph.M2M, false, instancemetadata.UsersTable, instancemetadata.UsersPrimaryKey...),
)
fromV = sqlgraph.Neighbors(im.driver.Dialect(), step)
return fromV, nil
}
return query
}
// QueryModerators queries the moderators edge of a InstanceMetadata.
func (c *InstanceMetadataClient) QueryModerators(im *InstanceMetadata) *UserQuery {
query := (&UserClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := im.ID
step := sqlgraph.NewStep(
sqlgraph.From(instancemetadata.Table, instancemetadata.FieldID, id),
sqlgraph.To(user.Table, user.FieldID),
sqlgraph.Edge(sqlgraph.M2M, false, instancemetadata.ModeratorsTable, instancemetadata.ModeratorsPrimaryKey...),
)
fromV = sqlgraph.Neighbors(im.driver.Dialect(), step)
return fromV, nil
}
return query
}
// QueryAdmins queries the admins edge of a InstanceMetadata.
func (c *InstanceMetadataClient) QueryAdmins(im *InstanceMetadata) *UserQuery {
query := (&UserClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := im.ID
step := sqlgraph.NewStep(
sqlgraph.From(instancemetadata.Table, instancemetadata.FieldID, id),
sqlgraph.To(user.Table, user.FieldID),
sqlgraph.Edge(sqlgraph.M2M, false, instancemetadata.AdminsTable, instancemetadata.AdminsPrimaryKey...),
)
fromV = sqlgraph.Neighbors(im.driver.Dialect(), step)
return fromV, nil
}
return query
}
// Hooks returns the client hooks.
func (c *InstanceMetadataClient) Hooks() []Hook {
return c.hooks.InstanceMetadata
}
// Interceptors returns the client interceptors.
func (c *InstanceMetadataClient) Interceptors() []Interceptor {
return c.inters.InstanceMetadata
}
func (c *InstanceMetadataClient) mutate(ctx context.Context, m *InstanceMetadataMutation) (Value, error) {
switch m.Op() {
case OpCreate:
return (&InstanceMetadataCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpUpdate:
return (&InstanceMetadataUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpUpdateOne:
return (&InstanceMetadataUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpDelete, OpDeleteOne:
return (&InstanceMetadataDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
default:
return nil, fmt.Errorf("ent: unknown InstanceMetadata mutation op: %q", m.Op())
}
}
// NoteClient is a client for the Note schema.
type NoteClient struct {
config
@ -874,171 +1055,6 @@ func (c *NoteClient) mutate(ctx context.Context, m *NoteMutation) (Value, error)
}
}
// ServerMetadataClient is a client for the ServerMetadata schema.
type ServerMetadataClient struct {
config
}
// NewServerMetadataClient returns a client for the ServerMetadata from the given config.
func NewServerMetadataClient(c config) *ServerMetadataClient {
return &ServerMetadataClient{config: c}
}
// Use adds a list of mutation hooks to the hooks stack.
// A call to `Use(f, g, h)` equals to `servermetadata.Hooks(f(g(h())))`.
func (c *ServerMetadataClient) Use(hooks ...Hook) {
c.hooks.ServerMetadata = append(c.hooks.ServerMetadata, hooks...)
}
// Intercept adds a list of query interceptors to the interceptors stack.
// A call to `Intercept(f, g, h)` equals to `servermetadata.Intercept(f(g(h())))`.
func (c *ServerMetadataClient) Intercept(interceptors ...Interceptor) {
c.inters.ServerMetadata = append(c.inters.ServerMetadata, interceptors...)
}
// Create returns a builder for creating a ServerMetadata entity.
func (c *ServerMetadataClient) Create() *ServerMetadataCreate {
mutation := newServerMetadataMutation(c.config, OpCreate)
return &ServerMetadataCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// CreateBulk returns a builder for creating a bulk of ServerMetadata entities.
func (c *ServerMetadataClient) CreateBulk(builders ...*ServerMetadataCreate) *ServerMetadataCreateBulk {
return &ServerMetadataCreateBulk{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 *ServerMetadataClient) MapCreateBulk(slice any, setFunc func(*ServerMetadataCreate, int)) *ServerMetadataCreateBulk {
rv := reflect.ValueOf(slice)
if rv.Kind() != reflect.Slice {
return &ServerMetadataCreateBulk{err: fmt.Errorf("calling to ServerMetadataClient.MapCreateBulk with wrong type %T, need slice", slice)}
}
builders := make([]*ServerMetadataCreate, rv.Len())
for i := 0; i < rv.Len(); i++ {
builders[i] = c.Create()
setFunc(builders[i], i)
}
return &ServerMetadataCreateBulk{config: c.config, builders: builders}
}
// Update returns an update builder for ServerMetadata.
func (c *ServerMetadataClient) Update() *ServerMetadataUpdate {
mutation := newServerMetadataMutation(c.config, OpUpdate)
return &ServerMetadataUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOne returns an update builder for the given entity.
func (c *ServerMetadataClient) UpdateOne(sm *ServerMetadata) *ServerMetadataUpdateOne {
mutation := newServerMetadataMutation(c.config, OpUpdateOne, withServerMetadata(sm))
return &ServerMetadataUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOneID returns an update builder for the given id.
func (c *ServerMetadataClient) UpdateOneID(id uuid.UUID) *ServerMetadataUpdateOne {
mutation := newServerMetadataMutation(c.config, OpUpdateOne, withServerMetadataID(id))
return &ServerMetadataUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// Delete returns a delete builder for ServerMetadata.
func (c *ServerMetadataClient) Delete() *ServerMetadataDelete {
mutation := newServerMetadataMutation(c.config, OpDelete)
return &ServerMetadataDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// DeleteOne returns a builder for deleting the given entity.
func (c *ServerMetadataClient) DeleteOne(sm *ServerMetadata) *ServerMetadataDeleteOne {
return c.DeleteOneID(sm.ID)
}
// DeleteOneID returns a builder for deleting the given entity by its id.
func (c *ServerMetadataClient) DeleteOneID(id uuid.UUID) *ServerMetadataDeleteOne {
builder := c.Delete().Where(servermetadata.ID(id))
builder.mutation.id = &id
builder.mutation.op = OpDeleteOne
return &ServerMetadataDeleteOne{builder}
}
// Query returns a query builder for ServerMetadata.
func (c *ServerMetadataClient) Query() *ServerMetadataQuery {
return &ServerMetadataQuery{
config: c.config,
ctx: &QueryContext{Type: TypeServerMetadata},
inters: c.Interceptors(),
}
}
// Get returns a ServerMetadata entity by its id.
func (c *ServerMetadataClient) Get(ctx context.Context, id uuid.UUID) (*ServerMetadata, error) {
return c.Query().Where(servermetadata.ID(id)).Only(ctx)
}
// GetX is like Get, but panics if an error occurs.
func (c *ServerMetadataClient) GetX(ctx context.Context, id uuid.UUID) *ServerMetadata {
obj, err := c.Get(ctx, id)
if err != nil {
panic(err)
}
return obj
}
// QueryFollower queries the follower edge of a ServerMetadata.
func (c *ServerMetadataClient) QueryFollower(sm *ServerMetadata) *UserQuery {
query := (&UserClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := sm.ID
step := sqlgraph.NewStep(
sqlgraph.From(servermetadata.Table, servermetadata.FieldID, id),
sqlgraph.To(user.Table, user.FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, servermetadata.FollowerTable, servermetadata.FollowerColumn),
)
fromV = sqlgraph.Neighbors(sm.driver.Dialect(), step)
return fromV, nil
}
return query
}
// QueryFollowee queries the followee edge of a ServerMetadata.
func (c *ServerMetadataClient) QueryFollowee(sm *ServerMetadata) *UserQuery {
query := (&UserClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := sm.ID
step := sqlgraph.NewStep(
sqlgraph.From(servermetadata.Table, servermetadata.FieldID, id),
sqlgraph.To(user.Table, user.FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, servermetadata.FolloweeTable, servermetadata.FolloweeColumn),
)
fromV = sqlgraph.Neighbors(sm.driver.Dialect(), step)
return fromV, nil
}
return query
}
// Hooks returns the client hooks.
func (c *ServerMetadataClient) Hooks() []Hook {
return c.hooks.ServerMetadata
}
// Interceptors returns the client interceptors.
func (c *ServerMetadataClient) Interceptors() []Interceptor {
return c.inters.ServerMetadata
}
func (c *ServerMetadataClient) mutate(ctx context.Context, m *ServerMetadataMutation) (Value, error) {
switch m.Op() {
case OpCreate:
return (&ServerMetadataCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpUpdate:
return (&ServerMetadataUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpUpdateOne:
return (&ServerMetadataUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpDelete, OpDeleteOne:
return (&ServerMetadataDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
default:
return nil, fmt.Errorf("ent: unknown ServerMetadata mutation op: %q", m.Op())
}
}
// UserClient is a client for the User schema.
type UserClient struct {
config
@ -1211,6 +1227,54 @@ func (c *UserClient) QueryMentionedNotes(u *User) *NoteQuery {
return query
}
// QueryServers queries the servers edge of a User.
func (c *UserClient) QueryServers(u *User) *InstanceMetadataQuery {
query := (&InstanceMetadataClient{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(instancemetadata.Table, instancemetadata.FieldID),
sqlgraph.Edge(sqlgraph.M2M, true, user.ServersTable, user.ServersPrimaryKey...),
)
fromV = sqlgraph.Neighbors(u.driver.Dialect(), step)
return fromV, nil
}
return query
}
// QueryModeratedServers queries the moderatedServers edge of a User.
func (c *UserClient) QueryModeratedServers(u *User) *InstanceMetadataQuery {
query := (&InstanceMetadataClient{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(instancemetadata.Table, instancemetadata.FieldID),
sqlgraph.Edge(sqlgraph.M2M, true, user.ModeratedServersTable, user.ModeratedServersPrimaryKey...),
)
fromV = sqlgraph.Neighbors(u.driver.Dialect(), step)
return fromV, nil
}
return query
}
// QueryAdministeredServers queries the administeredServers edge of a User.
func (c *UserClient) QueryAdministeredServers(u *User) *InstanceMetadataQuery {
query := (&InstanceMetadataClient{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(instancemetadata.Table, instancemetadata.FieldID),
sqlgraph.Edge(sqlgraph.M2M, true, user.AdministeredServersTable, user.AdministeredServersPrimaryKey...),
)
fromV = sqlgraph.Neighbors(u.driver.Dialect(), step)
return fromV, nil
}
return query
}
// Hooks returns the client hooks.
func (c *UserClient) Hooks() []Hook {
return c.hooks.User
@ -1239,9 +1303,9 @@ func (c *UserClient) mutate(ctx context.Context, m *UserMutation) (Value, error)
// hooks and interceptors per client, for fast access.
type (
hooks struct {
Attachment, Follow, Image, Note, ServerMetadata, User []ent.Hook
Attachment, Follow, Image, InstanceMetadata, Note, User []ent.Hook
}
inters struct {
Attachment, Follow, Image, Note, ServerMetadata, User []ent.Interceptor
Attachment, Follow, Image, InstanceMetadata, Note, User []ent.Interceptor
}
)

View file

@ -15,8 +15,8 @@ import (
"github.com/lysand-org/versia-go/ent/attachment"
"github.com/lysand-org/versia-go/ent/follow"
"github.com/lysand-org/versia-go/ent/image"
"github.com/lysand-org/versia-go/ent/instancemetadata"
"github.com/lysand-org/versia-go/ent/note"
"github.com/lysand-org/versia-go/ent/servermetadata"
"github.com/lysand-org/versia-go/ent/user"
)
@ -78,12 +78,12 @@ var (
func checkColumn(table, column string) error {
initCheck.Do(func() {
columnCheck = sql.NewColumnCheck(map[string]func(string) bool{
attachment.Table: attachment.ValidColumn,
follow.Table: follow.ValidColumn,
image.Table: image.ValidColumn,
note.Table: note.ValidColumn,
servermetadata.Table: servermetadata.ValidColumn,
user.Table: user.ValidColumn,
attachment.Table: attachment.ValidColumn,
follow.Table: follow.ValidColumn,
image.Table: image.ValidColumn,
instancemetadata.Table: instancemetadata.ValidColumn,
note.Table: note.ValidColumn,
user.Table: user.ValidColumn,
})
})
return columnCheck(table, column)

View file

@ -45,6 +45,18 @@ func (f ImageFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.ImageMutation", m)
}
// The InstanceMetadataFunc type is an adapter to allow the use of ordinary
// function as InstanceMetadata mutator.
type InstanceMetadataFunc func(context.Context, *ent.InstanceMetadataMutation) (ent.Value, error)
// Mutate calls f(ctx, m).
func (f InstanceMetadataFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
if mv, ok := m.(*ent.InstanceMetadataMutation); ok {
return f(ctx, mv)
}
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.InstanceMetadataMutation", m)
}
// The NoteFunc type is an adapter to allow the use of ordinary
// function as Note mutator.
type NoteFunc func(context.Context, *ent.NoteMutation) (ent.Value, error)
@ -57,18 +69,6 @@ func (f NoteFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error)
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.NoteMutation", m)
}
// The ServerMetadataFunc type is an adapter to allow the use of ordinary
// function as ServerMetadata mutator.
type ServerMetadataFunc func(context.Context, *ent.ServerMetadataMutation) (ent.Value, error)
// Mutate calls f(ctx, m).
func (f ServerMetadataFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
if mv, ok := m.(*ent.ServerMetadataMutation); ok {
return f(ctx, mv)
}
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.ServerMetadataMutation", 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)

View file

@ -36,6 +36,11 @@ func ValidColumn(column string) bool {
return false
}
var (
// URLValidator is a validator for the "url" field. It is called by the builders before save.
URLValidator func(string) error
)
// OrderOption defines the ordering options for the Image queries.
type OrderOption func(*sql.Selector)

View file

@ -70,6 +70,11 @@ func (ic *ImageCreate) check() error {
if _, ok := ic.mutation.URL(); !ok {
return &ValidationError{Name: "url", err: errors.New(`ent: missing required field "Image.url"`)}
}
if v, ok := ic.mutation.URL(); ok {
if err := image.URLValidator(v); err != nil {
return &ValidationError{Name: "url", err: fmt.Errorf(`ent: validator failed for field "Image.url": %w`, err)}
}
}
if _, ok := ic.mutation.MimeType(); !ok {
return &ValidationError{Name: "mimeType", err: errors.New(`ent: missing required field "Image.mimeType"`)}
}

View file

@ -87,7 +87,20 @@ func (iu *ImageUpdate) ExecX(ctx context.Context) {
}
}
// check runs all checks and user-defined validators on the builder.
func (iu *ImageUpdate) check() error {
if v, ok := iu.mutation.URL(); ok {
if err := image.URLValidator(v); err != nil {
return &ValidationError{Name: "url", err: fmt.Errorf(`ent: validator failed for field "Image.url": %w`, err)}
}
}
return nil
}
func (iu *ImageUpdate) sqlSave(ctx context.Context) (n int, err error) {
if err := iu.check(); err != nil {
return n, err
}
_spec := sqlgraph.NewUpdateSpec(image.Table, image.Columns, sqlgraph.NewFieldSpec(image.FieldID, field.TypeInt))
if ps := iu.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
@ -195,7 +208,20 @@ func (iuo *ImageUpdateOne) ExecX(ctx context.Context) {
}
}
// check runs all checks and user-defined validators on the builder.
func (iuo *ImageUpdateOne) check() error {
if v, ok := iuo.mutation.URL(); ok {
if err := image.URLValidator(v); err != nil {
return &ValidationError{Name: "url", err: fmt.Errorf(`ent: validator failed for field "Image.url": %w`, err)}
}
}
return nil
}
func (iuo *ImageUpdateOne) sqlSave(ctx context.Context) (_node *Image, err error) {
if err := iuo.check(); err != nil {
return _node, err
}
_spec := sqlgraph.NewUpdateSpec(image.Table, image.Columns, sqlgraph.NewFieldSpec(image.FieldID, field.TypeInt))
id, ok := iuo.mutation.ID()
if !ok {

429
ent/instancemetadata.go Normal file
View file

@ -0,0 +1,429 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"encoding/json"
"fmt"
"strings"
"time"
"entgo.io/ent"
"entgo.io/ent/dialect/sql"
"github.com/google/uuid"
"github.com/lysand-org/versia-go/ent/instancemetadata"
"github.com/lysand-org/versia-go/pkg/lysand"
)
// InstanceMetadata is the model entity for the InstanceMetadata schema.
type InstanceMetadata struct {
config `json:"-"`
// ID of the ent.
ID uuid.UUID `json:"id,omitempty"`
// IsRemote holds the value of the "isRemote" field.
IsRemote bool `json:"isRemote,omitempty"`
// URI holds the value of the "uri" field.
URI string `json:"uri,omitempty"`
// Extensions holds the value of the "extensions" field.
Extensions lysand.Extensions `json:"extensions,omitempty"`
// CreatedAt holds the value of the "created_at" field.
CreatedAt time.Time `json:"created_at,omitempty"`
// UpdatedAt holds the value of the "updated_at" field.
UpdatedAt time.Time `json:"updated_at,omitempty"`
// Name holds the value of the "name" field.
Name string `json:"name,omitempty"`
// Description holds the value of the "description" field.
Description *string `json:"description,omitempty"`
// Host holds the value of the "host" field.
Host string `json:"host,omitempty"`
// PublicKey holds the value of the "publicKey" field.
PublicKey []byte `json:"publicKey,omitempty"`
// PublicKeyAlgorithm holds the value of the "publicKeyAlgorithm" field.
PublicKeyAlgorithm string `json:"publicKeyAlgorithm,omitempty"`
// PrivateKey holds the value of the "privateKey" field.
PrivateKey []byte `json:"privateKey,omitempty"`
// SoftwareName holds the value of the "softwareName" field.
SoftwareName string `json:"softwareName,omitempty"`
// SoftwareVersion holds the value of the "softwareVersion" field.
SoftwareVersion string `json:"softwareVersion,omitempty"`
// SharedInboxURI holds the value of the "sharedInboxURI" field.
SharedInboxURI string `json:"sharedInboxURI,omitempty"`
// ModeratorsURI holds the value of the "moderatorsURI" field.
ModeratorsURI *string `json:"moderatorsURI,omitempty"`
// AdminsURI holds the value of the "adminsURI" field.
AdminsURI *string `json:"adminsURI,omitempty"`
// LogoEndpoint holds the value of the "logoEndpoint" field.
LogoEndpoint *string `json:"logoEndpoint,omitempty"`
// LogoMimeType holds the value of the "logoMimeType" field.
LogoMimeType *string `json:"logoMimeType,omitempty"`
// BannerEndpoint holds the value of the "bannerEndpoint" field.
BannerEndpoint *string `json:"bannerEndpoint,omitempty"`
// BannerMimeType holds the value of the "bannerMimeType" field.
BannerMimeType *string `json:"bannerMimeType,omitempty"`
// SupportedVersions holds the value of the "supportedVersions" field.
SupportedVersions []string `json:"supportedVersions,omitempty"`
// SupportedExtensions holds the value of the "supportedExtensions" field.
SupportedExtensions []string `json:"supportedExtensions,omitempty"`
// Edges holds the relations/edges for other nodes in the graph.
// The values are being populated by the InstanceMetadataQuery when eager-loading is set.
Edges InstanceMetadataEdges `json:"edges"`
selectValues sql.SelectValues
}
// InstanceMetadataEdges holds the relations/edges for other nodes in the graph.
type InstanceMetadataEdges struct {
// Users holds the value of the users edge.
Users []*User `json:"users,omitempty"`
// Moderators holds the value of the moderators edge.
Moderators []*User `json:"moderators,omitempty"`
// Admins holds the value of the admins edge.
Admins []*User `json:"admins,omitempty"`
// loadedTypes holds the information for reporting if a
// type was loaded (or requested) in eager-loading or not.
loadedTypes [3]bool
}
// UsersOrErr returns the Users value or an error if the edge
// was not loaded in eager-loading.
func (e InstanceMetadataEdges) UsersOrErr() ([]*User, error) {
if e.loadedTypes[0] {
return e.Users, nil
}
return nil, &NotLoadedError{edge: "users"}
}
// ModeratorsOrErr returns the Moderators value or an error if the edge
// was not loaded in eager-loading.
func (e InstanceMetadataEdges) ModeratorsOrErr() ([]*User, error) {
if e.loadedTypes[1] {
return e.Moderators, nil
}
return nil, &NotLoadedError{edge: "moderators"}
}
// AdminsOrErr returns the Admins value or an error if the edge
// was not loaded in eager-loading.
func (e InstanceMetadataEdges) AdminsOrErr() ([]*User, error) {
if e.loadedTypes[2] {
return e.Admins, nil
}
return nil, &NotLoadedError{edge: "admins"}
}
// scanValues returns the types for scanning values from sql.Rows.
func (*InstanceMetadata) scanValues(columns []string) ([]any, error) {
values := make([]any, len(columns))
for i := range columns {
switch columns[i] {
case instancemetadata.FieldExtensions, instancemetadata.FieldPublicKey, instancemetadata.FieldPrivateKey, instancemetadata.FieldSupportedVersions, instancemetadata.FieldSupportedExtensions:
values[i] = new([]byte)
case instancemetadata.FieldIsRemote:
values[i] = new(sql.NullBool)
case instancemetadata.FieldURI, instancemetadata.FieldName, instancemetadata.FieldDescription, instancemetadata.FieldHost, instancemetadata.FieldPublicKeyAlgorithm, instancemetadata.FieldSoftwareName, instancemetadata.FieldSoftwareVersion, instancemetadata.FieldSharedInboxURI, instancemetadata.FieldModeratorsURI, instancemetadata.FieldAdminsURI, instancemetadata.FieldLogoEndpoint, instancemetadata.FieldLogoMimeType, instancemetadata.FieldBannerEndpoint, instancemetadata.FieldBannerMimeType:
values[i] = new(sql.NullString)
case instancemetadata.FieldCreatedAt, instancemetadata.FieldUpdatedAt:
values[i] = new(sql.NullTime)
case instancemetadata.FieldID:
values[i] = new(uuid.UUID)
default:
values[i] = new(sql.UnknownType)
}
}
return values, nil
}
// assignValues assigns the values that were returned from sql.Rows (after scanning)
// to the InstanceMetadata fields.
func (im *InstanceMetadata) 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 instancemetadata.FieldID:
if value, ok := values[i].(*uuid.UUID); !ok {
return fmt.Errorf("unexpected type %T for field id", values[i])
} else if value != nil {
im.ID = *value
}
case instancemetadata.FieldIsRemote:
if value, ok := values[i].(*sql.NullBool); !ok {
return fmt.Errorf("unexpected type %T for field isRemote", values[i])
} else if value.Valid {
im.IsRemote = value.Bool
}
case instancemetadata.FieldURI:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field uri", values[i])
} else if value.Valid {
im.URI = value.String
}
case instancemetadata.FieldExtensions:
if value, ok := values[i].(*[]byte); !ok {
return fmt.Errorf("unexpected type %T for field extensions", values[i])
} else if value != nil && len(*value) > 0 {
if err := json.Unmarshal(*value, &im.Extensions); err != nil {
return fmt.Errorf("unmarshal field extensions: %w", err)
}
}
case instancemetadata.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 {
im.CreatedAt = value.Time
}
case instancemetadata.FieldUpdatedAt:
if value, ok := values[i].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field updated_at", values[i])
} else if value.Valid {
im.UpdatedAt = value.Time
}
case instancemetadata.FieldName:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field name", values[i])
} else if value.Valid {
im.Name = value.String
}
case instancemetadata.FieldDescription:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field description", values[i])
} else if value.Valid {
im.Description = new(string)
*im.Description = value.String
}
case instancemetadata.FieldHost:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field host", values[i])
} else if value.Valid {
im.Host = value.String
}
case instancemetadata.FieldPublicKey:
if value, ok := values[i].(*[]byte); !ok {
return fmt.Errorf("unexpected type %T for field publicKey", values[i])
} else if value != nil {
im.PublicKey = *value
}
case instancemetadata.FieldPublicKeyAlgorithm:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field publicKeyAlgorithm", values[i])
} else if value.Valid {
im.PublicKeyAlgorithm = value.String
}
case instancemetadata.FieldPrivateKey:
if value, ok := values[i].(*[]byte); !ok {
return fmt.Errorf("unexpected type %T for field privateKey", values[i])
} else if value != nil {
im.PrivateKey = *value
}
case instancemetadata.FieldSoftwareName:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field softwareName", values[i])
} else if value.Valid {
im.SoftwareName = value.String
}
case instancemetadata.FieldSoftwareVersion:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field softwareVersion", values[i])
} else if value.Valid {
im.SoftwareVersion = value.String
}
case instancemetadata.FieldSharedInboxURI:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field sharedInboxURI", values[i])
} else if value.Valid {
im.SharedInboxURI = value.String
}
case instancemetadata.FieldModeratorsURI:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field moderatorsURI", values[i])
} else if value.Valid {
im.ModeratorsURI = new(string)
*im.ModeratorsURI = value.String
}
case instancemetadata.FieldAdminsURI:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field adminsURI", values[i])
} else if value.Valid {
im.AdminsURI = new(string)
*im.AdminsURI = value.String
}
case instancemetadata.FieldLogoEndpoint:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field logoEndpoint", values[i])
} else if value.Valid {
im.LogoEndpoint = new(string)
*im.LogoEndpoint = value.String
}
case instancemetadata.FieldLogoMimeType:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field logoMimeType", values[i])
} else if value.Valid {
im.LogoMimeType = new(string)
*im.LogoMimeType = value.String
}
case instancemetadata.FieldBannerEndpoint:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field bannerEndpoint", values[i])
} else if value.Valid {
im.BannerEndpoint = new(string)
*im.BannerEndpoint = value.String
}
case instancemetadata.FieldBannerMimeType:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field bannerMimeType", values[i])
} else if value.Valid {
im.BannerMimeType = new(string)
*im.BannerMimeType = value.String
}
case instancemetadata.FieldSupportedVersions:
if value, ok := values[i].(*[]byte); !ok {
return fmt.Errorf("unexpected type %T for field supportedVersions", values[i])
} else if value != nil && len(*value) > 0 {
if err := json.Unmarshal(*value, &im.SupportedVersions); err != nil {
return fmt.Errorf("unmarshal field supportedVersions: %w", err)
}
}
case instancemetadata.FieldSupportedExtensions:
if value, ok := values[i].(*[]byte); !ok {
return fmt.Errorf("unexpected type %T for field supportedExtensions", values[i])
} else if value != nil && len(*value) > 0 {
if err := json.Unmarshal(*value, &im.SupportedExtensions); err != nil {
return fmt.Errorf("unmarshal field supportedExtensions: %w", err)
}
}
default:
im.selectValues.Set(columns[i], values[i])
}
}
return nil
}
// Value returns the ent.Value that was dynamically selected and assigned to the InstanceMetadata.
// This includes values selected through modifiers, order, etc.
func (im *InstanceMetadata) Value(name string) (ent.Value, error) {
return im.selectValues.Get(name)
}
// QueryUsers queries the "users" edge of the InstanceMetadata entity.
func (im *InstanceMetadata) QueryUsers() *UserQuery {
return NewInstanceMetadataClient(im.config).QueryUsers(im)
}
// QueryModerators queries the "moderators" edge of the InstanceMetadata entity.
func (im *InstanceMetadata) QueryModerators() *UserQuery {
return NewInstanceMetadataClient(im.config).QueryModerators(im)
}
// QueryAdmins queries the "admins" edge of the InstanceMetadata entity.
func (im *InstanceMetadata) QueryAdmins() *UserQuery {
return NewInstanceMetadataClient(im.config).QueryAdmins(im)
}
// Update returns a builder for updating this InstanceMetadata.
// Note that you need to call InstanceMetadata.Unwrap() before calling this method if this InstanceMetadata
// was returned from a transaction, and the transaction was committed or rolled back.
func (im *InstanceMetadata) Update() *InstanceMetadataUpdateOne {
return NewInstanceMetadataClient(im.config).UpdateOne(im)
}
// Unwrap unwraps the InstanceMetadata 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 (im *InstanceMetadata) Unwrap() *InstanceMetadata {
_tx, ok := im.config.driver.(*txDriver)
if !ok {
panic("ent: InstanceMetadata is not a transactional entity")
}
im.config.driver = _tx.drv
return im
}
// String implements the fmt.Stringer.
func (im *InstanceMetadata) String() string {
var builder strings.Builder
builder.WriteString("InstanceMetadata(")
builder.WriteString(fmt.Sprintf("id=%v, ", im.ID))
builder.WriteString("isRemote=")
builder.WriteString(fmt.Sprintf("%v", im.IsRemote))
builder.WriteString(", ")
builder.WriteString("uri=")
builder.WriteString(im.URI)
builder.WriteString(", ")
builder.WriteString("extensions=")
builder.WriteString(fmt.Sprintf("%v", im.Extensions))
builder.WriteString(", ")
builder.WriteString("created_at=")
builder.WriteString(im.CreatedAt.Format(time.ANSIC))
builder.WriteString(", ")
builder.WriteString("updated_at=")
builder.WriteString(im.UpdatedAt.Format(time.ANSIC))
builder.WriteString(", ")
builder.WriteString("name=")
builder.WriteString(im.Name)
builder.WriteString(", ")
if v := im.Description; v != nil {
builder.WriteString("description=")
builder.WriteString(*v)
}
builder.WriteString(", ")
builder.WriteString("host=")
builder.WriteString(im.Host)
builder.WriteString(", ")
builder.WriteString("publicKey=")
builder.WriteString(fmt.Sprintf("%v", im.PublicKey))
builder.WriteString(", ")
builder.WriteString("publicKeyAlgorithm=")
builder.WriteString(im.PublicKeyAlgorithm)
builder.WriteString(", ")
builder.WriteString("privateKey=")
builder.WriteString(fmt.Sprintf("%v", im.PrivateKey))
builder.WriteString(", ")
builder.WriteString("softwareName=")
builder.WriteString(im.SoftwareName)
builder.WriteString(", ")
builder.WriteString("softwareVersion=")
builder.WriteString(im.SoftwareVersion)
builder.WriteString(", ")
builder.WriteString("sharedInboxURI=")
builder.WriteString(im.SharedInboxURI)
builder.WriteString(", ")
if v := im.ModeratorsURI; v != nil {
builder.WriteString("moderatorsURI=")
builder.WriteString(*v)
}
builder.WriteString(", ")
if v := im.AdminsURI; v != nil {
builder.WriteString("adminsURI=")
builder.WriteString(*v)
}
builder.WriteString(", ")
if v := im.LogoEndpoint; v != nil {
builder.WriteString("logoEndpoint=")
builder.WriteString(*v)
}
builder.WriteString(", ")
if v := im.LogoMimeType; v != nil {
builder.WriteString("logoMimeType=")
builder.WriteString(*v)
}
builder.WriteString(", ")
if v := im.BannerEndpoint; v != nil {
builder.WriteString("bannerEndpoint=")
builder.WriteString(*v)
}
builder.WriteString(", ")
if v := im.BannerMimeType; v != nil {
builder.WriteString("bannerMimeType=")
builder.WriteString(*v)
}
builder.WriteString(", ")
builder.WriteString("supportedVersions=")
builder.WriteString(fmt.Sprintf("%v", im.SupportedVersions))
builder.WriteString(", ")
builder.WriteString("supportedExtensions=")
builder.WriteString(fmt.Sprintf("%v", im.SupportedExtensions))
builder.WriteByte(')')
return builder.String()
}
// InstanceMetadataSlice is a parsable slice of InstanceMetadata.
type InstanceMetadataSlice []*InstanceMetadata

View file

@ -0,0 +1,332 @@
// Code generated by ent, DO NOT EDIT.
package instancemetadata
import (
"time"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"github.com/google/uuid"
"github.com/lysand-org/versia-go/pkg/lysand"
)
const (
// Label holds the string label denoting the instancemetadata type in the database.
Label = "instance_metadata"
// FieldID holds the string denoting the id field in the database.
FieldID = "id"
// FieldIsRemote holds the string denoting the isremote field in the database.
FieldIsRemote = "is_remote"
// FieldURI holds the string denoting the uri field in the database.
FieldURI = "uri"
// FieldExtensions holds the string denoting the extensions field in the database.
FieldExtensions = "extensions"
// FieldCreatedAt holds the string denoting the created_at field in the database.
FieldCreatedAt = "created_at"
// FieldUpdatedAt holds the string denoting the updated_at field in the database.
FieldUpdatedAt = "updated_at"
// FieldName holds the string denoting the name field in the database.
FieldName = "name"
// FieldDescription holds the string denoting the description field in the database.
FieldDescription = "description"
// FieldHost holds the string denoting the host field in the database.
FieldHost = "host"
// FieldPublicKey holds the string denoting the publickey field in the database.
FieldPublicKey = "public_key"
// FieldPublicKeyAlgorithm holds the string denoting the publickeyalgorithm field in the database.
FieldPublicKeyAlgorithm = "public_key_algorithm"
// FieldPrivateKey holds the string denoting the privatekey field in the database.
FieldPrivateKey = "private_key"
// FieldSoftwareName holds the string denoting the softwarename field in the database.
FieldSoftwareName = "software_name"
// FieldSoftwareVersion holds the string denoting the softwareversion field in the database.
FieldSoftwareVersion = "software_version"
// FieldSharedInboxURI holds the string denoting the sharedinboxuri field in the database.
FieldSharedInboxURI = "shared_inbox_uri"
// FieldModeratorsURI holds the string denoting the moderatorsuri field in the database.
FieldModeratorsURI = "moderators_uri"
// FieldAdminsURI holds the string denoting the adminsuri field in the database.
FieldAdminsURI = "admins_uri"
// FieldLogoEndpoint holds the string denoting the logoendpoint field in the database.
FieldLogoEndpoint = "logo_endpoint"
// FieldLogoMimeType holds the string denoting the logomimetype field in the database.
FieldLogoMimeType = "logo_mime_type"
// FieldBannerEndpoint holds the string denoting the bannerendpoint field in the database.
FieldBannerEndpoint = "banner_endpoint"
// FieldBannerMimeType holds the string denoting the bannermimetype field in the database.
FieldBannerMimeType = "banner_mime_type"
// FieldSupportedVersions holds the string denoting the supportedversions field in the database.
FieldSupportedVersions = "supported_versions"
// FieldSupportedExtensions holds the string denoting the supportedextensions field in the database.
FieldSupportedExtensions = "supported_extensions"
// EdgeUsers holds the string denoting the users edge name in mutations.
EdgeUsers = "users"
// EdgeModerators holds the string denoting the moderators edge name in mutations.
EdgeModerators = "moderators"
// EdgeAdmins holds the string denoting the admins edge name in mutations.
EdgeAdmins = "admins"
// Table holds the table name of the instancemetadata in the database.
Table = "instance_metadata"
// UsersTable is the table that holds the users relation/edge. The primary key declared below.
UsersTable = "instance_metadata_users"
// UsersInverseTable is the table name for the User entity.
// It exists in this package in order to avoid circular dependency with the "user" package.
UsersInverseTable = "users"
// ModeratorsTable is the table that holds the moderators relation/edge. The primary key declared below.
ModeratorsTable = "instance_metadata_moderators"
// ModeratorsInverseTable is the table name for the User entity.
// It exists in this package in order to avoid circular dependency with the "user" package.
ModeratorsInverseTable = "users"
// AdminsTable is the table that holds the admins relation/edge. The primary key declared below.
AdminsTable = "instance_metadata_admins"
// AdminsInverseTable is the table name for the User entity.
// It exists in this package in order to avoid circular dependency with the "user" package.
AdminsInverseTable = "users"
)
// Columns holds all SQL columns for instancemetadata fields.
var Columns = []string{
FieldID,
FieldIsRemote,
FieldURI,
FieldExtensions,
FieldCreatedAt,
FieldUpdatedAt,
FieldName,
FieldDescription,
FieldHost,
FieldPublicKey,
FieldPublicKeyAlgorithm,
FieldPrivateKey,
FieldSoftwareName,
FieldSoftwareVersion,
FieldSharedInboxURI,
FieldModeratorsURI,
FieldAdminsURI,
FieldLogoEndpoint,
FieldLogoMimeType,
FieldBannerEndpoint,
FieldBannerMimeType,
FieldSupportedVersions,
FieldSupportedExtensions,
}
var (
// UsersPrimaryKey and UsersColumn2 are the table columns denoting the
// primary key for the users relation (M2M).
UsersPrimaryKey = []string{"instance_metadata_id", "user_id"}
// ModeratorsPrimaryKey and ModeratorsColumn2 are the table columns denoting the
// primary key for the moderators relation (M2M).
ModeratorsPrimaryKey = []string{"instance_metadata_id", "user_id"}
// AdminsPrimaryKey and AdminsColumn2 are the table columns denoting the
// primary key for the admins relation (M2M).
AdminsPrimaryKey = []string{"instance_metadata_id", "user_id"}
)
// 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
}
var (
// URIValidator is a validator for the "uri" field. It is called by the builders before save.
URIValidator func(string) error
// DefaultExtensions holds the default value on creation for the "extensions" field.
DefaultExtensions lysand.Extensions
// DefaultCreatedAt holds the default value on creation for the "created_at" field.
DefaultCreatedAt func() time.Time
// DefaultUpdatedAt holds the default value on creation for the "updated_at" field.
DefaultUpdatedAt func() time.Time
// UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field.
UpdateDefaultUpdatedAt func() time.Time
// NameValidator is a validator for the "name" field. It is called by the builders before save.
NameValidator func(string) error
// HostValidator is a validator for the "host" field. It is called by the builders before save.
HostValidator func(string) error
// SoftwareNameValidator is a validator for the "softwareName" field. It is called by the builders before save.
SoftwareNameValidator func(string) error
// SoftwareVersionValidator is a validator for the "softwareVersion" field. It is called by the builders before save.
SoftwareVersionValidator func(string) error
// SharedInboxURIValidator is a validator for the "sharedInboxURI" field. It is called by the builders before save.
SharedInboxURIValidator func(string) error
// ModeratorsURIValidator is a validator for the "moderatorsURI" field. It is called by the builders before save.
ModeratorsURIValidator func(string) error
// AdminsURIValidator is a validator for the "adminsURI" field. It is called by the builders before save.
AdminsURIValidator func(string) error
// LogoEndpointValidator is a validator for the "logoEndpoint" field. It is called by the builders before save.
LogoEndpointValidator func(string) error
// LogoMimeTypeValidator is a validator for the "logoMimeType" field. It is called by the builders before save.
LogoMimeTypeValidator func(string) error
// BannerEndpointValidator is a validator for the "bannerEndpoint" field. It is called by the builders before save.
BannerEndpointValidator func(string) error
// BannerMimeTypeValidator is a validator for the "bannerMimeType" field. It is called by the builders before save.
BannerMimeTypeValidator func(string) error
// DefaultSupportedVersions holds the default value on creation for the "supportedVersions" field.
DefaultSupportedVersions []string
// DefaultSupportedExtensions holds the default value on creation for the "supportedExtensions" field.
DefaultSupportedExtensions []string
// DefaultID holds the default value on creation for the "id" field.
DefaultID func() uuid.UUID
)
// OrderOption defines the ordering options for the InstanceMetadata 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()
}
// ByIsRemote orders the results by the isRemote field.
func ByIsRemote(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldIsRemote, opts...).ToFunc()
}
// ByURI orders the results by the uri field.
func ByURI(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldURI, opts...).ToFunc()
}
// ByCreatedAt orders the results by the created_at field.
func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldCreatedAt, opts...).ToFunc()
}
// ByUpdatedAt orders the results by the updated_at field.
func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc()
}
// ByName orders the results by the name field.
func ByName(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldName, opts...).ToFunc()
}
// ByDescription orders the results by the description field.
func ByDescription(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldDescription, opts...).ToFunc()
}
// ByHost orders the results by the host field.
func ByHost(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldHost, opts...).ToFunc()
}
// ByPublicKeyAlgorithm orders the results by the publicKeyAlgorithm field.
func ByPublicKeyAlgorithm(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldPublicKeyAlgorithm, opts...).ToFunc()
}
// BySoftwareName orders the results by the softwareName field.
func BySoftwareName(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldSoftwareName, opts...).ToFunc()
}
// BySoftwareVersion orders the results by the softwareVersion field.
func BySoftwareVersion(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldSoftwareVersion, opts...).ToFunc()
}
// BySharedInboxURI orders the results by the sharedInboxURI field.
func BySharedInboxURI(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldSharedInboxURI, opts...).ToFunc()
}
// ByModeratorsURI orders the results by the moderatorsURI field.
func ByModeratorsURI(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldModeratorsURI, opts...).ToFunc()
}
// ByAdminsURI orders the results by the adminsURI field.
func ByAdminsURI(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldAdminsURI, opts...).ToFunc()
}
// ByLogoEndpoint orders the results by the logoEndpoint field.
func ByLogoEndpoint(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldLogoEndpoint, opts...).ToFunc()
}
// ByLogoMimeType orders the results by the logoMimeType field.
func ByLogoMimeType(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldLogoMimeType, opts...).ToFunc()
}
// ByBannerEndpoint orders the results by the bannerEndpoint field.
func ByBannerEndpoint(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldBannerEndpoint, opts...).ToFunc()
}
// ByBannerMimeType orders the results by the bannerMimeType field.
func ByBannerMimeType(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldBannerMimeType, opts...).ToFunc()
}
// ByUsersCount orders the results by users count.
func ByUsersCount(opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborsCount(s, newUsersStep(), opts...)
}
}
// ByUsers orders the results by users terms.
func ByUsers(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newUsersStep(), append([]sql.OrderTerm{term}, terms...)...)
}
}
// ByModeratorsCount orders the results by moderators count.
func ByModeratorsCount(opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborsCount(s, newModeratorsStep(), opts...)
}
}
// ByModerators orders the results by moderators terms.
func ByModerators(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newModeratorsStep(), append([]sql.OrderTerm{term}, terms...)...)
}
}
// ByAdminsCount orders the results by admins count.
func ByAdminsCount(opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborsCount(s, newAdminsStep(), opts...)
}
}
// ByAdmins orders the results by admins terms.
func ByAdmins(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newAdminsStep(), append([]sql.OrderTerm{term}, terms...)...)
}
}
func newUsersStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(UsersInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.M2M, false, UsersTable, UsersPrimaryKey...),
)
}
func newModeratorsStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(ModeratorsInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.M2M, false, ModeratorsTable, ModeratorsPrimaryKey...),
)
}
func newAdminsStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(AdminsInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.M2M, false, AdminsTable, AdminsPrimaryKey...),
)
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,88 @@
// 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"
"github.com/lysand-org/versia-go/ent/instancemetadata"
"github.com/lysand-org/versia-go/ent/predicate"
)
// InstanceMetadataDelete is the builder for deleting a InstanceMetadata entity.
type InstanceMetadataDelete struct {
config
hooks []Hook
mutation *InstanceMetadataMutation
}
// Where appends a list predicates to the InstanceMetadataDelete builder.
func (imd *InstanceMetadataDelete) Where(ps ...predicate.InstanceMetadata) *InstanceMetadataDelete {
imd.mutation.Where(ps...)
return imd
}
// Exec executes the deletion query and returns how many vertices were deleted.
func (imd *InstanceMetadataDelete) Exec(ctx context.Context) (int, error) {
return withHooks(ctx, imd.sqlExec, imd.mutation, imd.hooks)
}
// ExecX is like Exec, but panics if an error occurs.
func (imd *InstanceMetadataDelete) ExecX(ctx context.Context) int {
n, err := imd.Exec(ctx)
if err != nil {
panic(err)
}
return n
}
func (imd *InstanceMetadataDelete) sqlExec(ctx context.Context) (int, error) {
_spec := sqlgraph.NewDeleteSpec(instancemetadata.Table, sqlgraph.NewFieldSpec(instancemetadata.FieldID, field.TypeUUID))
if ps := imd.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
affected, err := sqlgraph.DeleteNodes(ctx, imd.driver, _spec)
if err != nil && sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
imd.mutation.done = true
return affected, err
}
// InstanceMetadataDeleteOne is the builder for deleting a single InstanceMetadata entity.
type InstanceMetadataDeleteOne struct {
imd *InstanceMetadataDelete
}
// Where appends a list predicates to the InstanceMetadataDelete builder.
func (imdo *InstanceMetadataDeleteOne) Where(ps ...predicate.InstanceMetadata) *InstanceMetadataDeleteOne {
imdo.imd.mutation.Where(ps...)
return imdo
}
// Exec executes the deletion query.
func (imdo *InstanceMetadataDeleteOne) Exec(ctx context.Context) error {
n, err := imdo.imd.Exec(ctx)
switch {
case err != nil:
return err
case n == 0:
return &NotFoundError{instancemetadata.Label}
default:
return nil
}
}
// ExecX is like Exec, but panics if an error occurs.
func (imdo *InstanceMetadataDeleteOne) ExecX(ctx context.Context) {
if err := imdo.Exec(ctx); err != nil {
panic(err)
}
}

View file

@ -0,0 +1,845 @@
// 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"
"github.com/google/uuid"
"github.com/lysand-org/versia-go/ent/instancemetadata"
"github.com/lysand-org/versia-go/ent/predicate"
"github.com/lysand-org/versia-go/ent/user"
)
// InstanceMetadataQuery is the builder for querying InstanceMetadata entities.
type InstanceMetadataQuery struct {
config
ctx *QueryContext
order []instancemetadata.OrderOption
inters []Interceptor
predicates []predicate.InstanceMetadata
withUsers *UserQuery
withModerators *UserQuery
withAdmins *UserQuery
// intermediate query (i.e. traversal path).
sql *sql.Selector
path func(context.Context) (*sql.Selector, error)
}
// Where adds a new predicate for the InstanceMetadataQuery builder.
func (imq *InstanceMetadataQuery) Where(ps ...predicate.InstanceMetadata) *InstanceMetadataQuery {
imq.predicates = append(imq.predicates, ps...)
return imq
}
// Limit the number of records to be returned by this query.
func (imq *InstanceMetadataQuery) Limit(limit int) *InstanceMetadataQuery {
imq.ctx.Limit = &limit
return imq
}
// Offset to start from.
func (imq *InstanceMetadataQuery) Offset(offset int) *InstanceMetadataQuery {
imq.ctx.Offset = &offset
return imq
}
// 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 (imq *InstanceMetadataQuery) Unique(unique bool) *InstanceMetadataQuery {
imq.ctx.Unique = &unique
return imq
}
// Order specifies how the records should be ordered.
func (imq *InstanceMetadataQuery) Order(o ...instancemetadata.OrderOption) *InstanceMetadataQuery {
imq.order = append(imq.order, o...)
return imq
}
// QueryUsers chains the current query on the "users" edge.
func (imq *InstanceMetadataQuery) QueryUsers() *UserQuery {
query := (&UserClient{config: imq.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := imq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := imq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(instancemetadata.Table, instancemetadata.FieldID, selector),
sqlgraph.To(user.Table, user.FieldID),
sqlgraph.Edge(sqlgraph.M2M, false, instancemetadata.UsersTable, instancemetadata.UsersPrimaryKey...),
)
fromU = sqlgraph.SetNeighbors(imq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// QueryModerators chains the current query on the "moderators" edge.
func (imq *InstanceMetadataQuery) QueryModerators() *UserQuery {
query := (&UserClient{config: imq.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := imq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := imq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(instancemetadata.Table, instancemetadata.FieldID, selector),
sqlgraph.To(user.Table, user.FieldID),
sqlgraph.Edge(sqlgraph.M2M, false, instancemetadata.ModeratorsTable, instancemetadata.ModeratorsPrimaryKey...),
)
fromU = sqlgraph.SetNeighbors(imq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// QueryAdmins chains the current query on the "admins" edge.
func (imq *InstanceMetadataQuery) QueryAdmins() *UserQuery {
query := (&UserClient{config: imq.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := imq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := imq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(instancemetadata.Table, instancemetadata.FieldID, selector),
sqlgraph.To(user.Table, user.FieldID),
sqlgraph.Edge(sqlgraph.M2M, false, instancemetadata.AdminsTable, instancemetadata.AdminsPrimaryKey...),
)
fromU = sqlgraph.SetNeighbors(imq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// First returns the first InstanceMetadata entity from the query.
// Returns a *NotFoundError when no InstanceMetadata was found.
func (imq *InstanceMetadataQuery) First(ctx context.Context) (*InstanceMetadata, error) {
nodes, err := imq.Limit(1).All(setContextOp(ctx, imq.ctx, "First"))
if err != nil {
return nil, err
}
if len(nodes) == 0 {
return nil, &NotFoundError{instancemetadata.Label}
}
return nodes[0], nil
}
// FirstX is like First, but panics if an error occurs.
func (imq *InstanceMetadataQuery) FirstX(ctx context.Context) *InstanceMetadata {
node, err := imq.First(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return node
}
// FirstID returns the first InstanceMetadata ID from the query.
// Returns a *NotFoundError when no InstanceMetadata ID was found.
func (imq *InstanceMetadataQuery) FirstID(ctx context.Context) (id uuid.UUID, err error) {
var ids []uuid.UUID
if ids, err = imq.Limit(1).IDs(setContextOp(ctx, imq.ctx, "FirstID")); err != nil {
return
}
if len(ids) == 0 {
err = &NotFoundError{instancemetadata.Label}
return
}
return ids[0], nil
}
// FirstIDX is like FirstID, but panics if an error occurs.
func (imq *InstanceMetadataQuery) FirstIDX(ctx context.Context) uuid.UUID {
id, err := imq.FirstID(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return id
}
// Only returns a single InstanceMetadata entity found by the query, ensuring it only returns one.
// Returns a *NotSingularError when more than one InstanceMetadata entity is found.
// Returns a *NotFoundError when no InstanceMetadata entities are found.
func (imq *InstanceMetadataQuery) Only(ctx context.Context) (*InstanceMetadata, error) {
nodes, err := imq.Limit(2).All(setContextOp(ctx, imq.ctx, "Only"))
if err != nil {
return nil, err
}
switch len(nodes) {
case 1:
return nodes[0], nil
case 0:
return nil, &NotFoundError{instancemetadata.Label}
default:
return nil, &NotSingularError{instancemetadata.Label}
}
}
// OnlyX is like Only, but panics if an error occurs.
func (imq *InstanceMetadataQuery) OnlyX(ctx context.Context) *InstanceMetadata {
node, err := imq.Only(ctx)
if err != nil {
panic(err)
}
return node
}
// OnlyID is like Only, but returns the only InstanceMetadata ID in the query.
// Returns a *NotSingularError when more than one InstanceMetadata ID is found.
// Returns a *NotFoundError when no entities are found.
func (imq *InstanceMetadataQuery) OnlyID(ctx context.Context) (id uuid.UUID, err error) {
var ids []uuid.UUID
if ids, err = imq.Limit(2).IDs(setContextOp(ctx, imq.ctx, "OnlyID")); err != nil {
return
}
switch len(ids) {
case 1:
id = ids[0]
case 0:
err = &NotFoundError{instancemetadata.Label}
default:
err = &NotSingularError{instancemetadata.Label}
}
return
}
// OnlyIDX is like OnlyID, but panics if an error occurs.
func (imq *InstanceMetadataQuery) OnlyIDX(ctx context.Context) uuid.UUID {
id, err := imq.OnlyID(ctx)
if err != nil {
panic(err)
}
return id
}
// All executes the query and returns a list of InstanceMetadataSlice.
func (imq *InstanceMetadataQuery) All(ctx context.Context) ([]*InstanceMetadata, error) {
ctx = setContextOp(ctx, imq.ctx, "All")
if err := imq.prepareQuery(ctx); err != nil {
return nil, err
}
qr := querierAll[[]*InstanceMetadata, *InstanceMetadataQuery]()
return withInterceptors[[]*InstanceMetadata](ctx, imq, qr, imq.inters)
}
// AllX is like All, but panics if an error occurs.
func (imq *InstanceMetadataQuery) AllX(ctx context.Context) []*InstanceMetadata {
nodes, err := imq.All(ctx)
if err != nil {
panic(err)
}
return nodes
}
// IDs executes the query and returns a list of InstanceMetadata IDs.
func (imq *InstanceMetadataQuery) IDs(ctx context.Context) (ids []uuid.UUID, err error) {
if imq.ctx.Unique == nil && imq.path != nil {
imq.Unique(true)
}
ctx = setContextOp(ctx, imq.ctx, "IDs")
if err = imq.Select(instancemetadata.FieldID).Scan(ctx, &ids); err != nil {
return nil, err
}
return ids, nil
}
// IDsX is like IDs, but panics if an error occurs.
func (imq *InstanceMetadataQuery) IDsX(ctx context.Context) []uuid.UUID {
ids, err := imq.IDs(ctx)
if err != nil {
panic(err)
}
return ids
}
// Count returns the count of the given query.
func (imq *InstanceMetadataQuery) Count(ctx context.Context) (int, error) {
ctx = setContextOp(ctx, imq.ctx, "Count")
if err := imq.prepareQuery(ctx); err != nil {
return 0, err
}
return withInterceptors[int](ctx, imq, querierCount[*InstanceMetadataQuery](), imq.inters)
}
// CountX is like Count, but panics if an error occurs.
func (imq *InstanceMetadataQuery) CountX(ctx context.Context) int {
count, err := imq.Count(ctx)
if err != nil {
panic(err)
}
return count
}
// Exist returns true if the query has elements in the graph.
func (imq *InstanceMetadataQuery) Exist(ctx context.Context) (bool, error) {
ctx = setContextOp(ctx, imq.ctx, "Exist")
switch _, err := imq.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 (imq *InstanceMetadataQuery) ExistX(ctx context.Context) bool {
exist, err := imq.Exist(ctx)
if err != nil {
panic(err)
}
return exist
}
// Clone returns a duplicate of the InstanceMetadataQuery builder, including all associated steps. It can be
// used to prepare common query builders and use them differently after the clone is made.
func (imq *InstanceMetadataQuery) Clone() *InstanceMetadataQuery {
if imq == nil {
return nil
}
return &InstanceMetadataQuery{
config: imq.config,
ctx: imq.ctx.Clone(),
order: append([]instancemetadata.OrderOption{}, imq.order...),
inters: append([]Interceptor{}, imq.inters...),
predicates: append([]predicate.InstanceMetadata{}, imq.predicates...),
withUsers: imq.withUsers.Clone(),
withModerators: imq.withModerators.Clone(),
withAdmins: imq.withAdmins.Clone(),
// clone intermediate query.
sql: imq.sql.Clone(),
path: imq.path,
}
}
// WithUsers tells the query-builder to eager-load the nodes that are connected to
// the "users" edge. The optional arguments are used to configure the query builder of the edge.
func (imq *InstanceMetadataQuery) WithUsers(opts ...func(*UserQuery)) *InstanceMetadataQuery {
query := (&UserClient{config: imq.config}).Query()
for _, opt := range opts {
opt(query)
}
imq.withUsers = query
return imq
}
// WithModerators tells the query-builder to eager-load the nodes that are connected to
// the "moderators" edge. The optional arguments are used to configure the query builder of the edge.
func (imq *InstanceMetadataQuery) WithModerators(opts ...func(*UserQuery)) *InstanceMetadataQuery {
query := (&UserClient{config: imq.config}).Query()
for _, opt := range opts {
opt(query)
}
imq.withModerators = query
return imq
}
// WithAdmins tells the query-builder to eager-load the nodes that are connected to
// the "admins" edge. The optional arguments are used to configure the query builder of the edge.
func (imq *InstanceMetadataQuery) WithAdmins(opts ...func(*UserQuery)) *InstanceMetadataQuery {
query := (&UserClient{config: imq.config}).Query()
for _, opt := range opts {
opt(query)
}
imq.withAdmins = query
return imq
}
// 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 {
// IsRemote bool `json:"isRemote,omitempty"`
// Count int `json:"count,omitempty"`
// }
//
// client.InstanceMetadata.Query().
// GroupBy(instancemetadata.FieldIsRemote).
// Aggregate(ent.Count()).
// Scan(ctx, &v)
func (imq *InstanceMetadataQuery) GroupBy(field string, fields ...string) *InstanceMetadataGroupBy {
imq.ctx.Fields = append([]string{field}, fields...)
grbuild := &InstanceMetadataGroupBy{build: imq}
grbuild.flds = &imq.ctx.Fields
grbuild.label = instancemetadata.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 {
// IsRemote bool `json:"isRemote,omitempty"`
// }
//
// client.InstanceMetadata.Query().
// Select(instancemetadata.FieldIsRemote).
// Scan(ctx, &v)
func (imq *InstanceMetadataQuery) Select(fields ...string) *InstanceMetadataSelect {
imq.ctx.Fields = append(imq.ctx.Fields, fields...)
sbuild := &InstanceMetadataSelect{InstanceMetadataQuery: imq}
sbuild.label = instancemetadata.Label
sbuild.flds, sbuild.scan = &imq.ctx.Fields, sbuild.Scan
return sbuild
}
// Aggregate returns a InstanceMetadataSelect configured with the given aggregations.
func (imq *InstanceMetadataQuery) Aggregate(fns ...AggregateFunc) *InstanceMetadataSelect {
return imq.Select().Aggregate(fns...)
}
func (imq *InstanceMetadataQuery) prepareQuery(ctx context.Context) error {
for _, inter := range imq.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, imq); err != nil {
return err
}
}
}
for _, f := range imq.ctx.Fields {
if !instancemetadata.ValidColumn(f) {
return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
}
}
if imq.path != nil {
prev, err := imq.path(ctx)
if err != nil {
return err
}
imq.sql = prev
}
return nil
}
func (imq *InstanceMetadataQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*InstanceMetadata, error) {
var (
nodes = []*InstanceMetadata{}
_spec = imq.querySpec()
loadedTypes = [3]bool{
imq.withUsers != nil,
imq.withModerators != nil,
imq.withAdmins != nil,
}
)
_spec.ScanValues = func(columns []string) ([]any, error) {
return (*InstanceMetadata).scanValues(nil, columns)
}
_spec.Assign = func(columns []string, values []any) error {
node := &InstanceMetadata{config: imq.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, imq.driver, _spec); err != nil {
return nil, err
}
if len(nodes) == 0 {
return nodes, nil
}
if query := imq.withUsers; query != nil {
if err := imq.loadUsers(ctx, query, nodes,
func(n *InstanceMetadata) { n.Edges.Users = []*User{} },
func(n *InstanceMetadata, e *User) { n.Edges.Users = append(n.Edges.Users, e) }); err != nil {
return nil, err
}
}
if query := imq.withModerators; query != nil {
if err := imq.loadModerators(ctx, query, nodes,
func(n *InstanceMetadata) { n.Edges.Moderators = []*User{} },
func(n *InstanceMetadata, e *User) { n.Edges.Moderators = append(n.Edges.Moderators, e) }); err != nil {
return nil, err
}
}
if query := imq.withAdmins; query != nil {
if err := imq.loadAdmins(ctx, query, nodes,
func(n *InstanceMetadata) { n.Edges.Admins = []*User{} },
func(n *InstanceMetadata, e *User) { n.Edges.Admins = append(n.Edges.Admins, e) }); err != nil {
return nil, err
}
}
return nodes, nil
}
func (imq *InstanceMetadataQuery) loadUsers(ctx context.Context, query *UserQuery, nodes []*InstanceMetadata, init func(*InstanceMetadata), assign func(*InstanceMetadata, *User)) error {
edgeIDs := make([]driver.Value, len(nodes))
byID := make(map[uuid.UUID]*InstanceMetadata)
nids := make(map[uuid.UUID]map[*InstanceMetadata]struct{})
for i, node := range nodes {
edgeIDs[i] = node.ID
byID[node.ID] = node
if init != nil {
init(node)
}
}
query.Where(func(s *sql.Selector) {
joinT := sql.Table(instancemetadata.UsersTable)
s.Join(joinT).On(s.C(user.FieldID), joinT.C(instancemetadata.UsersPrimaryKey[1]))
s.Where(sql.InValues(joinT.C(instancemetadata.UsersPrimaryKey[0]), edgeIDs...))
columns := s.SelectedColumns()
s.Select(joinT.C(instancemetadata.UsersPrimaryKey[0]))
s.AppendSelect(columns...)
s.SetDistinct(false)
})
if err := query.prepareQuery(ctx); err != nil {
return err
}
qr := QuerierFunc(func(ctx context.Context, q Query) (Value, error) {
return query.sqlAll(ctx, func(_ context.Context, spec *sqlgraph.QuerySpec) {
assign := spec.Assign
values := spec.ScanValues
spec.ScanValues = func(columns []string) ([]any, error) {
values, err := values(columns[1:])
if err != nil {
return nil, err
}
return append([]any{new(uuid.UUID)}, values...), nil
}
spec.Assign = func(columns []string, values []any) error {
outValue := *values[0].(*uuid.UUID)
inValue := *values[1].(*uuid.UUID)
if nids[inValue] == nil {
nids[inValue] = map[*InstanceMetadata]struct{}{byID[outValue]: {}}
return assign(columns[1:], values[1:])
}
nids[inValue][byID[outValue]] = struct{}{}
return nil
}
})
})
neighbors, err := withInterceptors[[]*User](ctx, query, qr, query.inters)
if err != nil {
return err
}
for _, n := range neighbors {
nodes, ok := nids[n.ID]
if !ok {
return fmt.Errorf(`unexpected "users" node returned %v`, n.ID)
}
for kn := range nodes {
assign(kn, n)
}
}
return nil
}
func (imq *InstanceMetadataQuery) loadModerators(ctx context.Context, query *UserQuery, nodes []*InstanceMetadata, init func(*InstanceMetadata), assign func(*InstanceMetadata, *User)) error {
edgeIDs := make([]driver.Value, len(nodes))
byID := make(map[uuid.UUID]*InstanceMetadata)
nids := make(map[uuid.UUID]map[*InstanceMetadata]struct{})
for i, node := range nodes {
edgeIDs[i] = node.ID
byID[node.ID] = node
if init != nil {
init(node)
}
}
query.Where(func(s *sql.Selector) {
joinT := sql.Table(instancemetadata.ModeratorsTable)
s.Join(joinT).On(s.C(user.FieldID), joinT.C(instancemetadata.ModeratorsPrimaryKey[1]))
s.Where(sql.InValues(joinT.C(instancemetadata.ModeratorsPrimaryKey[0]), edgeIDs...))
columns := s.SelectedColumns()
s.Select(joinT.C(instancemetadata.ModeratorsPrimaryKey[0]))
s.AppendSelect(columns...)
s.SetDistinct(false)
})
if err := query.prepareQuery(ctx); err != nil {
return err
}
qr := QuerierFunc(func(ctx context.Context, q Query) (Value, error) {
return query.sqlAll(ctx, func(_ context.Context, spec *sqlgraph.QuerySpec) {
assign := spec.Assign
values := spec.ScanValues
spec.ScanValues = func(columns []string) ([]any, error) {
values, err := values(columns[1:])
if err != nil {
return nil, err
}
return append([]any{new(uuid.UUID)}, values...), nil
}
spec.Assign = func(columns []string, values []any) error {
outValue := *values[0].(*uuid.UUID)
inValue := *values[1].(*uuid.UUID)
if nids[inValue] == nil {
nids[inValue] = map[*InstanceMetadata]struct{}{byID[outValue]: {}}
return assign(columns[1:], values[1:])
}
nids[inValue][byID[outValue]] = struct{}{}
return nil
}
})
})
neighbors, err := withInterceptors[[]*User](ctx, query, qr, query.inters)
if err != nil {
return err
}
for _, n := range neighbors {
nodes, ok := nids[n.ID]
if !ok {
return fmt.Errorf(`unexpected "moderators" node returned %v`, n.ID)
}
for kn := range nodes {
assign(kn, n)
}
}
return nil
}
func (imq *InstanceMetadataQuery) loadAdmins(ctx context.Context, query *UserQuery, nodes []*InstanceMetadata, init func(*InstanceMetadata), assign func(*InstanceMetadata, *User)) error {
edgeIDs := make([]driver.Value, len(nodes))
byID := make(map[uuid.UUID]*InstanceMetadata)
nids := make(map[uuid.UUID]map[*InstanceMetadata]struct{})
for i, node := range nodes {
edgeIDs[i] = node.ID
byID[node.ID] = node
if init != nil {
init(node)
}
}
query.Where(func(s *sql.Selector) {
joinT := sql.Table(instancemetadata.AdminsTable)
s.Join(joinT).On(s.C(user.FieldID), joinT.C(instancemetadata.AdminsPrimaryKey[1]))
s.Where(sql.InValues(joinT.C(instancemetadata.AdminsPrimaryKey[0]), edgeIDs...))
columns := s.SelectedColumns()
s.Select(joinT.C(instancemetadata.AdminsPrimaryKey[0]))
s.AppendSelect(columns...)
s.SetDistinct(false)
})
if err := query.prepareQuery(ctx); err != nil {
return err
}
qr := QuerierFunc(func(ctx context.Context, q Query) (Value, error) {
return query.sqlAll(ctx, func(_ context.Context, spec *sqlgraph.QuerySpec) {
assign := spec.Assign
values := spec.ScanValues
spec.ScanValues = func(columns []string) ([]any, error) {
values, err := values(columns[1:])
if err != nil {
return nil, err
}
return append([]any{new(uuid.UUID)}, values...), nil
}
spec.Assign = func(columns []string, values []any) error {
outValue := *values[0].(*uuid.UUID)
inValue := *values[1].(*uuid.UUID)
if nids[inValue] == nil {
nids[inValue] = map[*InstanceMetadata]struct{}{byID[outValue]: {}}
return assign(columns[1:], values[1:])
}
nids[inValue][byID[outValue]] = struct{}{}
return nil
}
})
})
neighbors, err := withInterceptors[[]*User](ctx, query, qr, query.inters)
if err != nil {
return err
}
for _, n := range neighbors {
nodes, ok := nids[n.ID]
if !ok {
return fmt.Errorf(`unexpected "admins" node returned %v`, n.ID)
}
for kn := range nodes {
assign(kn, n)
}
}
return nil
}
func (imq *InstanceMetadataQuery) sqlCount(ctx context.Context) (int, error) {
_spec := imq.querySpec()
_spec.Node.Columns = imq.ctx.Fields
if len(imq.ctx.Fields) > 0 {
_spec.Unique = imq.ctx.Unique != nil && *imq.ctx.Unique
}
return sqlgraph.CountNodes(ctx, imq.driver, _spec)
}
func (imq *InstanceMetadataQuery) querySpec() *sqlgraph.QuerySpec {
_spec := sqlgraph.NewQuerySpec(instancemetadata.Table, instancemetadata.Columns, sqlgraph.NewFieldSpec(instancemetadata.FieldID, field.TypeUUID))
_spec.From = imq.sql
if unique := imq.ctx.Unique; unique != nil {
_spec.Unique = *unique
} else if imq.path != nil {
_spec.Unique = true
}
if fields := imq.ctx.Fields; len(fields) > 0 {
_spec.Node.Columns = make([]string, 0, len(fields))
_spec.Node.Columns = append(_spec.Node.Columns, instancemetadata.FieldID)
for i := range fields {
if fields[i] != instancemetadata.FieldID {
_spec.Node.Columns = append(_spec.Node.Columns, fields[i])
}
}
}
if ps := imq.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if limit := imq.ctx.Limit; limit != nil {
_spec.Limit = *limit
}
if offset := imq.ctx.Offset; offset != nil {
_spec.Offset = *offset
}
if ps := imq.order; len(ps) > 0 {
_spec.Order = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
return _spec
}
func (imq *InstanceMetadataQuery) sqlQuery(ctx context.Context) *sql.Selector {
builder := sql.Dialect(imq.driver.Dialect())
t1 := builder.Table(instancemetadata.Table)
columns := imq.ctx.Fields
if len(columns) == 0 {
columns = instancemetadata.Columns
}
selector := builder.Select(t1.Columns(columns...)...).From(t1)
if imq.sql != nil {
selector = imq.sql
selector.Select(selector.Columns(columns...)...)
}
if imq.ctx.Unique != nil && *imq.ctx.Unique {
selector.Distinct()
}
for _, p := range imq.predicates {
p(selector)
}
for _, p := range imq.order {
p(selector)
}
if offset := imq.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 := imq.ctx.Limit; limit != nil {
selector.Limit(*limit)
}
return selector
}
// InstanceMetadataGroupBy is the group-by builder for InstanceMetadata entities.
type InstanceMetadataGroupBy struct {
selector
build *InstanceMetadataQuery
}
// Aggregate adds the given aggregation functions to the group-by query.
func (imgb *InstanceMetadataGroupBy) Aggregate(fns ...AggregateFunc) *InstanceMetadataGroupBy {
imgb.fns = append(imgb.fns, fns...)
return imgb
}
// Scan applies the selector query and scans the result into the given value.
func (imgb *InstanceMetadataGroupBy) Scan(ctx context.Context, v any) error {
ctx = setContextOp(ctx, imgb.build.ctx, "GroupBy")
if err := imgb.build.prepareQuery(ctx); err != nil {
return err
}
return scanWithInterceptors[*InstanceMetadataQuery, *InstanceMetadataGroupBy](ctx, imgb.build, imgb, imgb.build.inters, v)
}
func (imgb *InstanceMetadataGroupBy) sqlScan(ctx context.Context, root *InstanceMetadataQuery, v any) error {
selector := root.sqlQuery(ctx).Select()
aggregation := make([]string, 0, len(imgb.fns))
for _, fn := range imgb.fns {
aggregation = append(aggregation, fn(selector))
}
if len(selector.SelectedColumns()) == 0 {
columns := make([]string, 0, len(*imgb.flds)+len(imgb.fns))
for _, f := range *imgb.flds {
columns = append(columns, selector.C(f))
}
columns = append(columns, aggregation...)
selector.Select(columns...)
}
selector.GroupBy(selector.Columns(*imgb.flds...)...)
if err := selector.Err(); err != nil {
return err
}
rows := &sql.Rows{}
query, args := selector.Query()
if err := imgb.build.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}
// InstanceMetadataSelect is the builder for selecting fields of InstanceMetadata entities.
type InstanceMetadataSelect struct {
*InstanceMetadataQuery
selector
}
// Aggregate adds the given aggregation functions to the selector query.
func (ims *InstanceMetadataSelect) Aggregate(fns ...AggregateFunc) *InstanceMetadataSelect {
ims.fns = append(ims.fns, fns...)
return ims
}
// Scan applies the selector query and scans the result into the given value.
func (ims *InstanceMetadataSelect) Scan(ctx context.Context, v any) error {
ctx = setContextOp(ctx, ims.ctx, "Select")
if err := ims.prepareQuery(ctx); err != nil {
return err
}
return scanWithInterceptors[*InstanceMetadataQuery, *InstanceMetadataSelect](ctx, ims.InstanceMetadataQuery, ims, ims.inters, v)
}
func (ims *InstanceMetadataSelect) sqlScan(ctx context.Context, root *InstanceMetadataQuery, v any) error {
selector := root.sqlQuery(ctx)
aggregation := make([]string, 0, len(ims.fns))
for _, fn := range ims.fns {
aggregation = append(aggregation, fn(selector))
}
switch n := len(*ims.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 := ims.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -98,6 +98,38 @@ var (
Columns: ImagesColumns,
PrimaryKey: []*schema.Column{ImagesColumns[0]},
}
// InstanceMetadataColumns holds the columns for the "instance_metadata" table.
InstanceMetadataColumns = []*schema.Column{
{Name: "id", Type: field.TypeUUID},
{Name: "is_remote", Type: field.TypeBool},
{Name: "uri", Type: field.TypeString},
{Name: "extensions", Type: field.TypeJSON},
{Name: "created_at", Type: field.TypeTime},
{Name: "updated_at", Type: field.TypeTime},
{Name: "name", Type: field.TypeString},
{Name: "description", Type: field.TypeString, Nullable: true},
{Name: "host", Type: field.TypeString, Unique: true},
{Name: "public_key", Type: field.TypeBytes},
{Name: "public_key_algorithm", Type: field.TypeString},
{Name: "private_key", Type: field.TypeBytes, Nullable: true},
{Name: "software_name", Type: field.TypeString},
{Name: "software_version", Type: field.TypeString},
{Name: "shared_inbox_uri", Type: field.TypeString},
{Name: "moderators_uri", Type: field.TypeString, Nullable: true},
{Name: "admins_uri", Type: field.TypeString, Nullable: true},
{Name: "logo_endpoint", Type: field.TypeString, Nullable: true},
{Name: "logo_mime_type", Type: field.TypeString, Nullable: true},
{Name: "banner_endpoint", Type: field.TypeString, Nullable: true},
{Name: "banner_mime_type", Type: field.TypeString, Nullable: true},
{Name: "supported_versions", Type: field.TypeJSON},
{Name: "supported_extensions", Type: field.TypeJSON},
}
// InstanceMetadataTable holds the schema information for the "instance_metadata" table.
InstanceMetadataTable = &schema.Table{
Name: "instance_metadata",
Columns: InstanceMetadataColumns,
PrimaryKey: []*schema.Column{InstanceMetadataColumns[0]},
}
// NotesColumns holds the columns for the "notes" table.
NotesColumns = []*schema.Column{
{Name: "id", Type: field.TypeUUID},
@ -126,48 +158,6 @@ var (
},
},
}
// ServerMetadataColumns holds the columns for the "server_metadata" table.
ServerMetadataColumns = []*schema.Column{
{Name: "id", Type: field.TypeUUID},
{Name: "is_remote", Type: field.TypeBool},
{Name: "uri", Type: field.TypeString},
{Name: "extensions", Type: field.TypeJSON},
{Name: "created_at", Type: field.TypeTime},
{Name: "updated_at", Type: field.TypeTime},
{Name: "name", Type: field.TypeString},
{Name: "description", Type: field.TypeString, Nullable: true},
{Name: "version", Type: field.TypeString},
{Name: "supported_extensions", Type: field.TypeJSON},
{Name: "server_metadata_follower", Type: field.TypeUUID},
{Name: "server_metadata_followee", Type: field.TypeUUID},
}
// ServerMetadataTable holds the schema information for the "server_metadata" table.
ServerMetadataTable = &schema.Table{
Name: "server_metadata",
Columns: ServerMetadataColumns,
PrimaryKey: []*schema.Column{ServerMetadataColumns[0]},
ForeignKeys: []*schema.ForeignKey{
{
Symbol: "server_metadata_users_follower",
Columns: []*schema.Column{ServerMetadataColumns[10]},
RefColumns: []*schema.Column{UsersColumns[0]},
OnDelete: schema.NoAction,
},
{
Symbol: "server_metadata_users_followee",
Columns: []*schema.Column{ServerMetadataColumns[11]},
RefColumns: []*schema.Column{UsersColumns[0]},
OnDelete: schema.NoAction,
},
},
Indexes: []*schema.Index{
{
Name: "servermetadata_server_metadata_follower_server_metadata_followee",
Unique: true,
Columns: []*schema.Column{ServerMetadataColumns[10], ServerMetadataColumns[11]},
},
},
}
// UsersColumns holds the columns for the "users" table.
UsersColumns = []*schema.Column{
{Name: "id", Type: field.TypeUUID},
@ -181,6 +171,8 @@ var (
{Name: "display_name", Type: field.TypeString, Nullable: true, Size: 256},
{Name: "biography", Type: field.TypeString, Nullable: true},
{Name: "public_key", Type: field.TypeBytes},
{Name: "public_key_actor", Type: field.TypeString},
{Name: "public_key_algorithm", Type: field.TypeString},
{Name: "private_key", Type: field.TypeBytes, Nullable: true},
{Name: "indexable", Type: field.TypeBool, Default: true},
{Name: "privacy_level", Type: field.TypeEnum, Enums: []string{"public", "restricted", "private"}, Default: "public"},
@ -201,18 +193,93 @@ var (
ForeignKeys: []*schema.ForeignKey{
{
Symbol: "users_images_avatarImage",
Columns: []*schema.Column{UsersColumns[20]},
Columns: []*schema.Column{UsersColumns[22]},
RefColumns: []*schema.Column{ImagesColumns[0]},
OnDelete: schema.SetNull,
},
{
Symbol: "users_images_headerImage",
Columns: []*schema.Column{UsersColumns[21]},
Columns: []*schema.Column{UsersColumns[23]},
RefColumns: []*schema.Column{ImagesColumns[0]},
OnDelete: schema.SetNull,
},
},
}
// InstanceMetadataUsersColumns holds the columns for the "instance_metadata_users" table.
InstanceMetadataUsersColumns = []*schema.Column{
{Name: "instance_metadata_id", Type: field.TypeUUID},
{Name: "user_id", Type: field.TypeUUID},
}
// InstanceMetadataUsersTable holds the schema information for the "instance_metadata_users" table.
InstanceMetadataUsersTable = &schema.Table{
Name: "instance_metadata_users",
Columns: InstanceMetadataUsersColumns,
PrimaryKey: []*schema.Column{InstanceMetadataUsersColumns[0], InstanceMetadataUsersColumns[1]},
ForeignKeys: []*schema.ForeignKey{
{
Symbol: "instance_metadata_users_instance_metadata_id",
Columns: []*schema.Column{InstanceMetadataUsersColumns[0]},
RefColumns: []*schema.Column{InstanceMetadataColumns[0]},
OnDelete: schema.Cascade,
},
{
Symbol: "instance_metadata_users_user_id",
Columns: []*schema.Column{InstanceMetadataUsersColumns[1]},
RefColumns: []*schema.Column{UsersColumns[0]},
OnDelete: schema.Cascade,
},
},
}
// InstanceMetadataModeratorsColumns holds the columns for the "instance_metadata_moderators" table.
InstanceMetadataModeratorsColumns = []*schema.Column{
{Name: "instance_metadata_id", Type: field.TypeUUID},
{Name: "user_id", Type: field.TypeUUID},
}
// InstanceMetadataModeratorsTable holds the schema information for the "instance_metadata_moderators" table.
InstanceMetadataModeratorsTable = &schema.Table{
Name: "instance_metadata_moderators",
Columns: InstanceMetadataModeratorsColumns,
PrimaryKey: []*schema.Column{InstanceMetadataModeratorsColumns[0], InstanceMetadataModeratorsColumns[1]},
ForeignKeys: []*schema.ForeignKey{
{
Symbol: "instance_metadata_moderators_instance_metadata_id",
Columns: []*schema.Column{InstanceMetadataModeratorsColumns[0]},
RefColumns: []*schema.Column{InstanceMetadataColumns[0]},
OnDelete: schema.Cascade,
},
{
Symbol: "instance_metadata_moderators_user_id",
Columns: []*schema.Column{InstanceMetadataModeratorsColumns[1]},
RefColumns: []*schema.Column{UsersColumns[0]},
OnDelete: schema.Cascade,
},
},
}
// InstanceMetadataAdminsColumns holds the columns for the "instance_metadata_admins" table.
InstanceMetadataAdminsColumns = []*schema.Column{
{Name: "instance_metadata_id", Type: field.TypeUUID},
{Name: "user_id", Type: field.TypeUUID},
}
// InstanceMetadataAdminsTable holds the schema information for the "instance_metadata_admins" table.
InstanceMetadataAdminsTable = &schema.Table{
Name: "instance_metadata_admins",
Columns: InstanceMetadataAdminsColumns,
PrimaryKey: []*schema.Column{InstanceMetadataAdminsColumns[0], InstanceMetadataAdminsColumns[1]},
ForeignKeys: []*schema.ForeignKey{
{
Symbol: "instance_metadata_admins_instance_metadata_id",
Columns: []*schema.Column{InstanceMetadataAdminsColumns[0]},
RefColumns: []*schema.Column{InstanceMetadataColumns[0]},
OnDelete: schema.Cascade,
},
{
Symbol: "instance_metadata_admins_user_id",
Columns: []*schema.Column{InstanceMetadataAdminsColumns[1]},
RefColumns: []*schema.Column{UsersColumns[0]},
OnDelete: schema.Cascade,
},
},
}
// NoteMentionsColumns holds the columns for the "note_mentions" table.
NoteMentionsColumns = []*schema.Column{
{Name: "note_id", Type: field.TypeUUID},
@ -243,9 +310,12 @@ var (
AttachmentsTable,
FollowsTable,
ImagesTable,
InstanceMetadataTable,
NotesTable,
ServerMetadataTable,
UsersTable,
InstanceMetadataUsersTable,
InstanceMetadataModeratorsTable,
InstanceMetadataAdminsTable,
NoteMentionsTable,
}
)
@ -256,10 +326,14 @@ func init() {
FollowsTable.ForeignKeys[0].RefTable = UsersTable
FollowsTable.ForeignKeys[1].RefTable = UsersTable
NotesTable.ForeignKeys[0].RefTable = UsersTable
ServerMetadataTable.ForeignKeys[0].RefTable = UsersTable
ServerMetadataTable.ForeignKeys[1].RefTable = UsersTable
UsersTable.ForeignKeys[0].RefTable = ImagesTable
UsersTable.ForeignKeys[1].RefTable = ImagesTable
InstanceMetadataUsersTable.ForeignKeys[0].RefTable = InstanceMetadataTable
InstanceMetadataUsersTable.ForeignKeys[1].RefTable = UsersTable
InstanceMetadataModeratorsTable.ForeignKeys[0].RefTable = InstanceMetadataTable
InstanceMetadataModeratorsTable.ForeignKeys[1].RefTable = UsersTable
InstanceMetadataAdminsTable.ForeignKeys[0].RefTable = InstanceMetadataTable
InstanceMetadataAdminsTable.ForeignKeys[1].RefTable = UsersTable
NoteMentionsTable.ForeignKeys[0].RefTable = NotesTable
NoteMentionsTable.ForeignKeys[1].RefTable = UsersTable
}

File diff suppressed because it is too large Load diff

View file

@ -15,11 +15,11 @@ type Follow func(*sql.Selector)
// Image is the predicate function for image builders.
type Image func(*sql.Selector)
// InstanceMetadata is the predicate function for instancemetadata builders.
type InstanceMetadata func(*sql.Selector)
// Note is the predicate function for note builders.
type Note func(*sql.Selector)
// ServerMetadata is the predicate function for servermetadata builders.
type ServerMetadata func(*sql.Selector)
// User is the predicate function for user builders.
type User func(*sql.Selector)

View file

@ -8,9 +8,10 @@ import (
"github.com/google/uuid"
"github.com/lysand-org/versia-go/ent/attachment"
"github.com/lysand-org/versia-go/ent/follow"
"github.com/lysand-org/versia-go/ent/image"
"github.com/lysand-org/versia-go/ent/instancemetadata"
"github.com/lysand-org/versia-go/ent/note"
"github.com/lysand-org/versia-go/ent/schema"
"github.com/lysand-org/versia-go/ent/servermetadata"
"github.com/lysand-org/versia-go/ent/user"
"github.com/lysand-org/versia-go/pkg/lysand"
)
@ -77,6 +78,91 @@ func init() {
followDescID := followMixinFields0[0].Descriptor()
// follow.DefaultID holds the default value on creation for the id field.
follow.DefaultID = followDescID.Default.(func() uuid.UUID)
imageFields := schema.Image{}.Fields()
_ = imageFields
// imageDescURL is the schema descriptor for url field.
imageDescURL := imageFields[0].Descriptor()
// image.URLValidator is a validator for the "url" field. It is called by the builders before save.
image.URLValidator = imageDescURL.Validators[0].(func(string) error)
instancemetadataMixin := schema.InstanceMetadata{}.Mixin()
instancemetadataMixinFields0 := instancemetadataMixin[0].Fields()
_ = instancemetadataMixinFields0
instancemetadataFields := schema.InstanceMetadata{}.Fields()
_ = instancemetadataFields
// instancemetadataDescURI is the schema descriptor for uri field.
instancemetadataDescURI := instancemetadataMixinFields0[2].Descriptor()
// instancemetadata.URIValidator is a validator for the "uri" field. It is called by the builders before save.
instancemetadata.URIValidator = instancemetadataDescURI.Validators[0].(func(string) error)
// instancemetadataDescExtensions is the schema descriptor for extensions field.
instancemetadataDescExtensions := instancemetadataMixinFields0[3].Descriptor()
// instancemetadata.DefaultExtensions holds the default value on creation for the extensions field.
instancemetadata.DefaultExtensions = instancemetadataDescExtensions.Default.(lysand.Extensions)
// instancemetadataDescCreatedAt is the schema descriptor for created_at field.
instancemetadataDescCreatedAt := instancemetadataMixinFields0[4].Descriptor()
// instancemetadata.DefaultCreatedAt holds the default value on creation for the created_at field.
instancemetadata.DefaultCreatedAt = instancemetadataDescCreatedAt.Default.(func() time.Time)
// instancemetadataDescUpdatedAt is the schema descriptor for updated_at field.
instancemetadataDescUpdatedAt := instancemetadataMixinFields0[5].Descriptor()
// instancemetadata.DefaultUpdatedAt holds the default value on creation for the updated_at field.
instancemetadata.DefaultUpdatedAt = instancemetadataDescUpdatedAt.Default.(func() time.Time)
// instancemetadata.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
instancemetadata.UpdateDefaultUpdatedAt = instancemetadataDescUpdatedAt.UpdateDefault.(func() time.Time)
// instancemetadataDescName is the schema descriptor for name field.
instancemetadataDescName := instancemetadataFields[0].Descriptor()
// instancemetadata.NameValidator is a validator for the "name" field. It is called by the builders before save.
instancemetadata.NameValidator = instancemetadataDescName.Validators[0].(func(string) error)
// instancemetadataDescHost is the schema descriptor for host field.
instancemetadataDescHost := instancemetadataFields[2].Descriptor()
// instancemetadata.HostValidator is a validator for the "host" field. It is called by the builders before save.
instancemetadata.HostValidator = instancemetadataDescHost.Validators[0].(func(string) error)
// instancemetadataDescSoftwareName is the schema descriptor for softwareName field.
instancemetadataDescSoftwareName := instancemetadataFields[6].Descriptor()
// instancemetadata.SoftwareNameValidator is a validator for the "softwareName" field. It is called by the builders before save.
instancemetadata.SoftwareNameValidator = instancemetadataDescSoftwareName.Validators[0].(func(string) error)
// instancemetadataDescSoftwareVersion is the schema descriptor for softwareVersion field.
instancemetadataDescSoftwareVersion := instancemetadataFields[7].Descriptor()
// instancemetadata.SoftwareVersionValidator is a validator for the "softwareVersion" field. It is called by the builders before save.
instancemetadata.SoftwareVersionValidator = instancemetadataDescSoftwareVersion.Validators[0].(func(string) error)
// instancemetadataDescSharedInboxURI is the schema descriptor for sharedInboxURI field.
instancemetadataDescSharedInboxURI := instancemetadataFields[8].Descriptor()
// instancemetadata.SharedInboxURIValidator is a validator for the "sharedInboxURI" field. It is called by the builders before save.
instancemetadata.SharedInboxURIValidator = instancemetadataDescSharedInboxURI.Validators[0].(func(string) error)
// instancemetadataDescModeratorsURI is the schema descriptor for moderatorsURI field.
instancemetadataDescModeratorsURI := instancemetadataFields[9].Descriptor()
// instancemetadata.ModeratorsURIValidator is a validator for the "moderatorsURI" field. It is called by the builders before save.
instancemetadata.ModeratorsURIValidator = instancemetadataDescModeratorsURI.Validators[0].(func(string) error)
// instancemetadataDescAdminsURI is the schema descriptor for adminsURI field.
instancemetadataDescAdminsURI := instancemetadataFields[10].Descriptor()
// instancemetadata.AdminsURIValidator is a validator for the "adminsURI" field. It is called by the builders before save.
instancemetadata.AdminsURIValidator = instancemetadataDescAdminsURI.Validators[0].(func(string) error)
// instancemetadataDescLogoEndpoint is the schema descriptor for logoEndpoint field.
instancemetadataDescLogoEndpoint := instancemetadataFields[11].Descriptor()
// instancemetadata.LogoEndpointValidator is a validator for the "logoEndpoint" field. It is called by the builders before save.
instancemetadata.LogoEndpointValidator = instancemetadataDescLogoEndpoint.Validators[0].(func(string) error)
// instancemetadataDescLogoMimeType is the schema descriptor for logoMimeType field.
instancemetadataDescLogoMimeType := instancemetadataFields[12].Descriptor()
// instancemetadata.LogoMimeTypeValidator is a validator for the "logoMimeType" field. It is called by the builders before save.
instancemetadata.LogoMimeTypeValidator = instancemetadataDescLogoMimeType.Validators[0].(func(string) error)
// instancemetadataDescBannerEndpoint is the schema descriptor for bannerEndpoint field.
instancemetadataDescBannerEndpoint := instancemetadataFields[13].Descriptor()
// instancemetadata.BannerEndpointValidator is a validator for the "bannerEndpoint" field. It is called by the builders before save.
instancemetadata.BannerEndpointValidator = instancemetadataDescBannerEndpoint.Validators[0].(func(string) error)
// instancemetadataDescBannerMimeType is the schema descriptor for bannerMimeType field.
instancemetadataDescBannerMimeType := instancemetadataFields[14].Descriptor()
// instancemetadata.BannerMimeTypeValidator is a validator for the "bannerMimeType" field. It is called by the builders before save.
instancemetadata.BannerMimeTypeValidator = instancemetadataDescBannerMimeType.Validators[0].(func(string) error)
// instancemetadataDescSupportedVersions is the schema descriptor for supportedVersions field.
instancemetadataDescSupportedVersions := instancemetadataFields[15].Descriptor()
// instancemetadata.DefaultSupportedVersions holds the default value on creation for the supportedVersions field.
instancemetadata.DefaultSupportedVersions = instancemetadataDescSupportedVersions.Default.([]string)
// instancemetadataDescSupportedExtensions is the schema descriptor for supportedExtensions field.
instancemetadataDescSupportedExtensions := instancemetadataFields[16].Descriptor()
// instancemetadata.DefaultSupportedExtensions holds the default value on creation for the supportedExtensions field.
instancemetadata.DefaultSupportedExtensions = instancemetadataDescSupportedExtensions.Default.([]string)
// instancemetadataDescID is the schema descriptor for id field.
instancemetadataDescID := instancemetadataMixinFields0[0].Descriptor()
// instancemetadata.DefaultID holds the default value on creation for the id field.
instancemetadata.DefaultID = instancemetadataDescID.Default.(func() uuid.UUID)
noteMixin := schema.Note{}.Mixin()
noteMixinFields0 := noteMixin[0].Fields()
_ = noteMixinFields0
@ -112,45 +198,6 @@ func init() {
noteDescID := noteMixinFields0[0].Descriptor()
// note.DefaultID holds the default value on creation for the id field.
note.DefaultID = noteDescID.Default.(func() uuid.UUID)
servermetadataMixin := schema.ServerMetadata{}.Mixin()
servermetadataMixinFields0 := servermetadataMixin[0].Fields()
_ = servermetadataMixinFields0
servermetadataFields := schema.ServerMetadata{}.Fields()
_ = servermetadataFields
// servermetadataDescURI is the schema descriptor for uri field.
servermetadataDescURI := servermetadataMixinFields0[2].Descriptor()
// servermetadata.URIValidator is a validator for the "uri" field. It is called by the builders before save.
servermetadata.URIValidator = servermetadataDescURI.Validators[0].(func(string) error)
// servermetadataDescExtensions is the schema descriptor for extensions field.
servermetadataDescExtensions := servermetadataMixinFields0[3].Descriptor()
// servermetadata.DefaultExtensions holds the default value on creation for the extensions field.
servermetadata.DefaultExtensions = servermetadataDescExtensions.Default.(lysand.Extensions)
// servermetadataDescCreatedAt is the schema descriptor for created_at field.
servermetadataDescCreatedAt := servermetadataMixinFields0[4].Descriptor()
// servermetadata.DefaultCreatedAt holds the default value on creation for the created_at field.
servermetadata.DefaultCreatedAt = servermetadataDescCreatedAt.Default.(func() time.Time)
// servermetadataDescUpdatedAt is the schema descriptor for updated_at field.
servermetadataDescUpdatedAt := servermetadataMixinFields0[5].Descriptor()
// servermetadata.DefaultUpdatedAt holds the default value on creation for the updated_at field.
servermetadata.DefaultUpdatedAt = servermetadataDescUpdatedAt.Default.(func() time.Time)
// servermetadata.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
servermetadata.UpdateDefaultUpdatedAt = servermetadataDescUpdatedAt.UpdateDefault.(func() time.Time)
// servermetadataDescName is the schema descriptor for name field.
servermetadataDescName := servermetadataFields[0].Descriptor()
// servermetadata.NameValidator is a validator for the "name" field. It is called by the builders before save.
servermetadata.NameValidator = servermetadataDescName.Validators[0].(func(string) error)
// servermetadataDescVersion is the schema descriptor for version field.
servermetadataDescVersion := servermetadataFields[2].Descriptor()
// servermetadata.VersionValidator is a validator for the "version" field. It is called by the builders before save.
servermetadata.VersionValidator = servermetadataDescVersion.Validators[0].(func(string) error)
// servermetadataDescSupportedExtensions is the schema descriptor for supportedExtensions field.
servermetadataDescSupportedExtensions := servermetadataFields[3].Descriptor()
// servermetadata.DefaultSupportedExtensions holds the default value on creation for the supportedExtensions field.
servermetadata.DefaultSupportedExtensions = servermetadataDescSupportedExtensions.Default.([]string)
// servermetadataDescID is the schema descriptor for id field.
servermetadataDescID := servermetadataMixinFields0[0].Descriptor()
// servermetadata.DefaultID holds the default value on creation for the id field.
servermetadata.DefaultID = servermetadataDescID.Default.(func() uuid.UUID)
userMixin := schema.User{}.Mixin()
userMixinFields0 := userMixin[0].Fields()
_ = userMixinFields0
@ -197,31 +244,31 @@ func init() {
// user.DisplayNameValidator is a validator for the "displayName" field. It is called by the builders before save.
user.DisplayNameValidator = userDescDisplayName.Validators[0].(func(string) error)
// userDescIndexable is the schema descriptor for indexable field.
userDescIndexable := userFields[6].Descriptor()
userDescIndexable := userFields[8].Descriptor()
// user.DefaultIndexable holds the default value on creation for the indexable field.
user.DefaultIndexable = userDescIndexable.Default.(bool)
// userDescFields is the schema descriptor for fields field.
userDescFields := userFields[8].Descriptor()
userDescFields := userFields[10].Descriptor()
// user.DefaultFields holds the default value on creation for the fields field.
user.DefaultFields = userDescFields.Default.([]lysand.Field)
// userDescInbox is the schema descriptor for inbox field.
userDescInbox := userFields[9].Descriptor()
userDescInbox := userFields[11].Descriptor()
// user.InboxValidator is a validator for the "inbox" field. It is called by the builders before save.
user.InboxValidator = userDescInbox.Validators[0].(func(string) error)
// userDescFeatured is the schema descriptor for featured field.
userDescFeatured := userFields[10].Descriptor()
userDescFeatured := userFields[12].Descriptor()
// user.FeaturedValidator is a validator for the "featured" field. It is called by the builders before save.
user.FeaturedValidator = userDescFeatured.Validators[0].(func(string) error)
// userDescFollowers is the schema descriptor for followers field.
userDescFollowers := userFields[11].Descriptor()
userDescFollowers := userFields[13].Descriptor()
// user.FollowersValidator is a validator for the "followers" field. It is called by the builders before save.
user.FollowersValidator = userDescFollowers.Validators[0].(func(string) error)
// userDescFollowing is the schema descriptor for following field.
userDescFollowing := userFields[12].Descriptor()
userDescFollowing := userFields[14].Descriptor()
// user.FollowingValidator is a validator for the "following" field. It is called by the builders before save.
user.FollowingValidator = userDescFollowing.Validators[0].(func(string) error)
// userDescOutbox is the schema descriptor for outbox field.
userDescOutbox := userFields[13].Descriptor()
userDescOutbox := userFields[15].Descriptor()
// user.OutboxValidator is a validator for the "outbox" field. It is called by the builders before save.
user.OutboxValidator = userDescOutbox.Validators[0].(func(string) error)
// userDescID is the schema descriptor for id field.

View file

@ -14,10 +14,18 @@ func (Attachment) Fields() []ent.Field {
field.Bytes("sha256"),
field.Int("size"),
field.String("blurhash").Optional().Nillable(),
field.Int("height").Optional().Nillable(),
field.Int("width").Optional().Nillable(),
field.Int("fps").Optional().Nillable(),
field.String("blurhash").
Optional().
Nillable(),
field.Int("height").
Optional().
Nillable(),
field.Int("width").
Optional().
Nillable(),
field.Int("fps").
Optional().
Nillable(),
field.String("mimeType"),
}

View file

@ -11,7 +11,9 @@ type Follow struct{ ent.Schema }
func (Follow) Fields() []ent.Field {
return []ent.Field{
field.Enum("status").Values("pending", "accepted").Default("pending"),
field.Enum("status").
Values("pending", "accepted").
Default("pending"),
}
}

View file

@ -9,7 +9,7 @@ type Image struct{ ent.Schema }
func (Image) Fields() []ent.Field {
return []ent.Field{
field.String("url"),
field.String("url").Validate(ValidateURI),
field.String("mimeType"),
}
}

View file

@ -0,0 +1,71 @@
package schema
import (
"entgo.io/ent"
"entgo.io/ent/schema/edge"
"entgo.io/ent/schema/field"
)
type InstanceMetadata struct{ ent.Schema }
func (InstanceMetadata) Fields() []ent.Field {
return []ent.Field{
field.String("name").NotEmpty(),
field.String("description").
Optional().
Nillable(),
field.String("host").
NotEmpty().
Unique(),
field.Bytes("publicKey"),
field.String("publicKeyAlgorithm"),
field.Bytes("privateKey").Optional(),
field.String("softwareName").NotEmpty(),
field.String("softwareVersion").NotEmpty(),
field.String("sharedInboxURI").Validate(ValidateURI),
field.String("moderatorsURI").
Validate(ValidateURI).
Optional().
Nillable(),
field.String("adminsURI").
Validate(ValidateURI).
Optional().
Nillable(),
field.String("logoEndpoint").
Validate(ValidateURI).
Optional().
Nillable(),
field.String("logoMimeType").
Validate(ValidateURI).
Optional().
Nillable(),
field.String("bannerEndpoint").
Validate(ValidateURI).
Optional().
Nillable(),
field.String("bannerMimeType").
Validate(ValidateURI).
Optional().
Nillable(),
field.Strings("supportedVersions").Default([]string{}),
field.Strings("supportedExtensions").Default([]string{}),
}
}
func (InstanceMetadata) Edges() []ent.Edge {
return []ent.Edge{
edge.To("users", User.Type),
edge.To("moderators", User.Type),
edge.To("admins", User.Type),
}
}
func (InstanceMetadata) Mixin() []ent.Mixin {
return []ent.Mixin{LysandEntityMixin{}}
}

View file

@ -1,43 +0,0 @@
package schema
import (
"entgo.io/ent"
"entgo.io/ent/schema/edge"
"entgo.io/ent/schema/field"
"entgo.io/ent/schema/index"
)
type ServerMetadata struct{ ent.Schema }
func (ServerMetadata) Fields() []ent.Field {
return []ent.Field{
field.String("name").
NotEmpty(),
field.String("description").
Optional().
Nillable(),
field.String("version").
NotEmpty(),
field.Strings("supportedExtensions").
Default([]string{}),
}
}
func (ServerMetadata) Edges() []ent.Edge {
return []ent.Edge{
edge.To("follower", User.Type).Unique().Required(),
edge.To("followee", User.Type).Unique().Required(),
}
}
func (ServerMetadata) Indexes() []ent.Index {
return []ent.Index{
index.Edges("follower", "followee").Unique(),
}
}
func (ServerMetadata) Mixin() []ent.Mixin {
return []ent.Mixin{LysandEntityMixin{}}
}

View file

@ -1,7 +1,6 @@
package schema
import (
"crypto/ed25519"
"errors"
"regexp"
@ -20,17 +19,31 @@ type User struct{ ent.Schema }
func (User) Fields() []ent.Field {
return []ent.Field{
field.String("username").Unique().MaxLen(32).Validate(ValidateUsername),
field.Bytes("passwordHash").Optional().Nillable(),
field.String("username").
Unique().
MaxLen(32).
Validate(ValidateUsername),
field.Bytes("passwordHash").
Optional().
Nillable(),
field.String("displayName").MaxLen(256).Optional().Nillable(),
field.String("biography").Optional().Nillable(),
field.String("displayName").
MaxLen(256).
Optional().
Nillable(),
field.String("biography").
Optional().
Nillable(),
field.Bytes("publicKey").GoType(ed25519.PublicKey([]byte{})),
field.Bytes("privateKey").GoType(ed25519.PrivateKey([]byte{})).Optional(),
field.Bytes("publicKey"),
field.String("publicKeyActor"),
field.String("publicKeyAlgorithm"),
field.Bytes("privateKey").Optional(),
field.Bool("indexable").Default(true),
field.Enum("privacyLevel").Values("public", "restricted", "private").Default("public"),
field.Enum("privacyLevel").
Values("public", "restricted", "private").
Default("public"),
field.JSON("fields", []lysand.Field{}).Default([]lysand.Field{}),
@ -51,6 +64,10 @@ func (User) Edges() []ent.Edge {
edge.From("authoredNotes", Note.Type).Ref("author"),
edge.From("mentionedNotes", Note.Type).Ref("mentions"),
edge.From("servers", InstanceMetadata.Type).Ref("users"),
edge.From("moderatedServers", InstanceMetadata.Type).Ref("moderators"),
edge.From("administeredServers", InstanceMetadata.Type).Ref("admins"),
}
}

View file

@ -1,275 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"encoding/json"
"fmt"
"strings"
"time"
"entgo.io/ent"
"entgo.io/ent/dialect/sql"
"github.com/google/uuid"
"github.com/lysand-org/versia-go/ent/servermetadata"
"github.com/lysand-org/versia-go/ent/user"
"github.com/lysand-org/versia-go/pkg/lysand"
)
// ServerMetadata is the model entity for the ServerMetadata schema.
type ServerMetadata struct {
config `json:"-"`
// ID of the ent.
ID uuid.UUID `json:"id,omitempty"`
// IsRemote holds the value of the "isRemote" field.
IsRemote bool `json:"isRemote,omitempty"`
// URI holds the value of the "uri" field.
URI string `json:"uri,omitempty"`
// Extensions holds the value of the "extensions" field.
Extensions lysand.Extensions `json:"extensions,omitempty"`
// CreatedAt holds the value of the "created_at" field.
CreatedAt time.Time `json:"created_at,omitempty"`
// UpdatedAt holds the value of the "updated_at" field.
UpdatedAt time.Time `json:"updated_at,omitempty"`
// Name holds the value of the "name" field.
Name string `json:"name,omitempty"`
// Description holds the value of the "description" field.
Description *string `json:"description,omitempty"`
// Version holds the value of the "version" field.
Version string `json:"version,omitempty"`
// SupportedExtensions holds the value of the "supportedExtensions" field.
SupportedExtensions []string `json:"supportedExtensions,omitempty"`
// Edges holds the relations/edges for other nodes in the graph.
// The values are being populated by the ServerMetadataQuery when eager-loading is set.
Edges ServerMetadataEdges `json:"edges"`
server_metadata_follower *uuid.UUID
server_metadata_followee *uuid.UUID
selectValues sql.SelectValues
}
// ServerMetadataEdges holds the relations/edges for other nodes in the graph.
type ServerMetadataEdges struct {
// Follower holds the value of the follower edge.
Follower *User `json:"follower,omitempty"`
// Followee holds the value of the followee edge.
Followee *User `json:"followee,omitempty"`
// loadedTypes holds the information for reporting if a
// type was loaded (or requested) in eager-loading or not.
loadedTypes [2]bool
}
// FollowerOrErr returns the Follower value or an error if the edge
// was not loaded in eager-loading, or loaded but was not found.
func (e ServerMetadataEdges) FollowerOrErr() (*User, error) {
if e.Follower != nil {
return e.Follower, nil
} else if e.loadedTypes[0] {
return nil, &NotFoundError{label: user.Label}
}
return nil, &NotLoadedError{edge: "follower"}
}
// FolloweeOrErr returns the Followee value or an error if the edge
// was not loaded in eager-loading, or loaded but was not found.
func (e ServerMetadataEdges) FolloweeOrErr() (*User, error) {
if e.Followee != nil {
return e.Followee, nil
} else if e.loadedTypes[1] {
return nil, &NotFoundError{label: user.Label}
}
return nil, &NotLoadedError{edge: "followee"}
}
// scanValues returns the types for scanning values from sql.Rows.
func (*ServerMetadata) scanValues(columns []string) ([]any, error) {
values := make([]any, len(columns))
for i := range columns {
switch columns[i] {
case servermetadata.FieldExtensions, servermetadata.FieldSupportedExtensions:
values[i] = new([]byte)
case servermetadata.FieldIsRemote:
values[i] = new(sql.NullBool)
case servermetadata.FieldURI, servermetadata.FieldName, servermetadata.FieldDescription, servermetadata.FieldVersion:
values[i] = new(sql.NullString)
case servermetadata.FieldCreatedAt, servermetadata.FieldUpdatedAt:
values[i] = new(sql.NullTime)
case servermetadata.FieldID:
values[i] = new(uuid.UUID)
case servermetadata.ForeignKeys[0]: // server_metadata_follower
values[i] = &sql.NullScanner{S: new(uuid.UUID)}
case servermetadata.ForeignKeys[1]: // server_metadata_followee
values[i] = &sql.NullScanner{S: new(uuid.UUID)}
default:
values[i] = new(sql.UnknownType)
}
}
return values, nil
}
// assignValues assigns the values that were returned from sql.Rows (after scanning)
// to the ServerMetadata fields.
func (sm *ServerMetadata) 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 servermetadata.FieldID:
if value, ok := values[i].(*uuid.UUID); !ok {
return fmt.Errorf("unexpected type %T for field id", values[i])
} else if value != nil {
sm.ID = *value
}
case servermetadata.FieldIsRemote:
if value, ok := values[i].(*sql.NullBool); !ok {
return fmt.Errorf("unexpected type %T for field isRemote", values[i])
} else if value.Valid {
sm.IsRemote = value.Bool
}
case servermetadata.FieldURI:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field uri", values[i])
} else if value.Valid {
sm.URI = value.String
}
case servermetadata.FieldExtensions:
if value, ok := values[i].(*[]byte); !ok {
return fmt.Errorf("unexpected type %T for field extensions", values[i])
} else if value != nil && len(*value) > 0 {
if err := json.Unmarshal(*value, &sm.Extensions); err != nil {
return fmt.Errorf("unmarshal field extensions: %w", err)
}
}
case servermetadata.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 {
sm.CreatedAt = value.Time
}
case servermetadata.FieldUpdatedAt:
if value, ok := values[i].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field updated_at", values[i])
} else if value.Valid {
sm.UpdatedAt = value.Time
}
case servermetadata.FieldName:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field name", values[i])
} else if value.Valid {
sm.Name = value.String
}
case servermetadata.FieldDescription:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field description", values[i])
} else if value.Valid {
sm.Description = new(string)
*sm.Description = value.String
}
case servermetadata.FieldVersion:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field version", values[i])
} else if value.Valid {
sm.Version = value.String
}
case servermetadata.FieldSupportedExtensions:
if value, ok := values[i].(*[]byte); !ok {
return fmt.Errorf("unexpected type %T for field supportedExtensions", values[i])
} else if value != nil && len(*value) > 0 {
if err := json.Unmarshal(*value, &sm.SupportedExtensions); err != nil {
return fmt.Errorf("unmarshal field supportedExtensions: %w", err)
}
}
case servermetadata.ForeignKeys[0]:
if value, ok := values[i].(*sql.NullScanner); !ok {
return fmt.Errorf("unexpected type %T for field server_metadata_follower", values[i])
} else if value.Valid {
sm.server_metadata_follower = new(uuid.UUID)
*sm.server_metadata_follower = *value.S.(*uuid.UUID)
}
case servermetadata.ForeignKeys[1]:
if value, ok := values[i].(*sql.NullScanner); !ok {
return fmt.Errorf("unexpected type %T for field server_metadata_followee", values[i])
} else if value.Valid {
sm.server_metadata_followee = new(uuid.UUID)
*sm.server_metadata_followee = *value.S.(*uuid.UUID)
}
default:
sm.selectValues.Set(columns[i], values[i])
}
}
return nil
}
// Value returns the ent.Value that was dynamically selected and assigned to the ServerMetadata.
// This includes values selected through modifiers, order, etc.
func (sm *ServerMetadata) Value(name string) (ent.Value, error) {
return sm.selectValues.Get(name)
}
// QueryFollower queries the "follower" edge of the ServerMetadata entity.
func (sm *ServerMetadata) QueryFollower() *UserQuery {
return NewServerMetadataClient(sm.config).QueryFollower(sm)
}
// QueryFollowee queries the "followee" edge of the ServerMetadata entity.
func (sm *ServerMetadata) QueryFollowee() *UserQuery {
return NewServerMetadataClient(sm.config).QueryFollowee(sm)
}
// Update returns a builder for updating this ServerMetadata.
// Note that you need to call ServerMetadata.Unwrap() before calling this method if this ServerMetadata
// was returned from a transaction, and the transaction was committed or rolled back.
func (sm *ServerMetadata) Update() *ServerMetadataUpdateOne {
return NewServerMetadataClient(sm.config).UpdateOne(sm)
}
// Unwrap unwraps the ServerMetadata 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 (sm *ServerMetadata) Unwrap() *ServerMetadata {
_tx, ok := sm.config.driver.(*txDriver)
if !ok {
panic("ent: ServerMetadata is not a transactional entity")
}
sm.config.driver = _tx.drv
return sm
}
// String implements the fmt.Stringer.
func (sm *ServerMetadata) String() string {
var builder strings.Builder
builder.WriteString("ServerMetadata(")
builder.WriteString(fmt.Sprintf("id=%v, ", sm.ID))
builder.WriteString("isRemote=")
builder.WriteString(fmt.Sprintf("%v", sm.IsRemote))
builder.WriteString(", ")
builder.WriteString("uri=")
builder.WriteString(sm.URI)
builder.WriteString(", ")
builder.WriteString("extensions=")
builder.WriteString(fmt.Sprintf("%v", sm.Extensions))
builder.WriteString(", ")
builder.WriteString("created_at=")
builder.WriteString(sm.CreatedAt.Format(time.ANSIC))
builder.WriteString(", ")
builder.WriteString("updated_at=")
builder.WriteString(sm.UpdatedAt.Format(time.ANSIC))
builder.WriteString(", ")
builder.WriteString("name=")
builder.WriteString(sm.Name)
builder.WriteString(", ")
if v := sm.Description; v != nil {
builder.WriteString("description=")
builder.WriteString(*v)
}
builder.WriteString(", ")
builder.WriteString("version=")
builder.WriteString(sm.Version)
builder.WriteString(", ")
builder.WriteString("supportedExtensions=")
builder.WriteString(fmt.Sprintf("%v", sm.SupportedExtensions))
builder.WriteByte(')')
return builder.String()
}
// ServerMetadataSlice is a parsable slice of ServerMetadata.
type ServerMetadataSlice []*ServerMetadata

View file

@ -1,185 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package servermetadata
import (
"time"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"github.com/google/uuid"
"github.com/lysand-org/versia-go/pkg/lysand"
)
const (
// Label holds the string label denoting the servermetadata type in the database.
Label = "server_metadata"
// FieldID holds the string denoting the id field in the database.
FieldID = "id"
// FieldIsRemote holds the string denoting the isremote field in the database.
FieldIsRemote = "is_remote"
// FieldURI holds the string denoting the uri field in the database.
FieldURI = "uri"
// FieldExtensions holds the string denoting the extensions field in the database.
FieldExtensions = "extensions"
// FieldCreatedAt holds the string denoting the created_at field in the database.
FieldCreatedAt = "created_at"
// FieldUpdatedAt holds the string denoting the updated_at field in the database.
FieldUpdatedAt = "updated_at"
// FieldName holds the string denoting the name field in the database.
FieldName = "name"
// FieldDescription holds the string denoting the description field in the database.
FieldDescription = "description"
// FieldVersion holds the string denoting the version field in the database.
FieldVersion = "version"
// FieldSupportedExtensions holds the string denoting the supportedextensions field in the database.
FieldSupportedExtensions = "supported_extensions"
// EdgeFollower holds the string denoting the follower edge name in mutations.
EdgeFollower = "follower"
// EdgeFollowee holds the string denoting the followee edge name in mutations.
EdgeFollowee = "followee"
// Table holds the table name of the servermetadata in the database.
Table = "server_metadata"
// FollowerTable is the table that holds the follower relation/edge.
FollowerTable = "server_metadata"
// FollowerInverseTable is the table name for the User entity.
// It exists in this package in order to avoid circular dependency with the "user" package.
FollowerInverseTable = "users"
// FollowerColumn is the table column denoting the follower relation/edge.
FollowerColumn = "server_metadata_follower"
// FolloweeTable is the table that holds the followee relation/edge.
FolloweeTable = "server_metadata"
// FolloweeInverseTable is the table name for the User entity.
// It exists in this package in order to avoid circular dependency with the "user" package.
FolloweeInverseTable = "users"
// FolloweeColumn is the table column denoting the followee relation/edge.
FolloweeColumn = "server_metadata_followee"
)
// Columns holds all SQL columns for servermetadata fields.
var Columns = []string{
FieldID,
FieldIsRemote,
FieldURI,
FieldExtensions,
FieldCreatedAt,
FieldUpdatedAt,
FieldName,
FieldDescription,
FieldVersion,
FieldSupportedExtensions,
}
// ForeignKeys holds the SQL foreign-keys that are owned by the "server_metadata"
// table and are not defined as standalone fields in the schema.
var ForeignKeys = []string{
"server_metadata_follower",
"server_metadata_followee",
}
// 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 (
// URIValidator is a validator for the "uri" field. It is called by the builders before save.
URIValidator func(string) error
// DefaultExtensions holds the default value on creation for the "extensions" field.
DefaultExtensions lysand.Extensions
// DefaultCreatedAt holds the default value on creation for the "created_at" field.
DefaultCreatedAt func() time.Time
// DefaultUpdatedAt holds the default value on creation for the "updated_at" field.
DefaultUpdatedAt func() time.Time
// UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field.
UpdateDefaultUpdatedAt func() time.Time
// NameValidator is a validator for the "name" field. It is called by the builders before save.
NameValidator func(string) error
// VersionValidator is a validator for the "version" field. It is called by the builders before save.
VersionValidator func(string) error
// DefaultSupportedExtensions holds the default value on creation for the "supportedExtensions" field.
DefaultSupportedExtensions []string
// DefaultID holds the default value on creation for the "id" field.
DefaultID func() uuid.UUID
)
// OrderOption defines the ordering options for the ServerMetadata 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()
}
// ByIsRemote orders the results by the isRemote field.
func ByIsRemote(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldIsRemote, opts...).ToFunc()
}
// ByURI orders the results by the uri field.
func ByURI(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldURI, opts...).ToFunc()
}
// ByCreatedAt orders the results by the created_at field.
func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldCreatedAt, opts...).ToFunc()
}
// ByUpdatedAt orders the results by the updated_at field.
func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc()
}
// ByName orders the results by the name field.
func ByName(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldName, opts...).ToFunc()
}
// ByDescription orders the results by the description field.
func ByDescription(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldDescription, opts...).ToFunc()
}
// ByVersion orders the results by the version field.
func ByVersion(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldVersion, opts...).ToFunc()
}
// ByFollowerField orders the results by follower field.
func ByFollowerField(field string, opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newFollowerStep(), sql.OrderByField(field, opts...))
}
}
// ByFolloweeField orders the results by followee field.
func ByFolloweeField(field string, opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newFolloweeStep(), sql.OrderByField(field, opts...))
}
}
func newFollowerStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(FollowerInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, FollowerTable, FollowerColumn),
)
}
func newFolloweeStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(FolloweeInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, FolloweeTable, FolloweeColumn),
)
}

View file

@ -1,513 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package servermetadata
import (
"time"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"github.com/google/uuid"
"github.com/lysand-org/versia-go/ent/predicate"
)
// ID filters vertices based on their ID field.
func ID(id uuid.UUID) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldEQ(FieldID, id))
}
// IDEQ applies the EQ predicate on the ID field.
func IDEQ(id uuid.UUID) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldEQ(FieldID, id))
}
// IDNEQ applies the NEQ predicate on the ID field.
func IDNEQ(id uuid.UUID) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldNEQ(FieldID, id))
}
// IDIn applies the In predicate on the ID field.
func IDIn(ids ...uuid.UUID) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldIn(FieldID, ids...))
}
// IDNotIn applies the NotIn predicate on the ID field.
func IDNotIn(ids ...uuid.UUID) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldNotIn(FieldID, ids...))
}
// IDGT applies the GT predicate on the ID field.
func IDGT(id uuid.UUID) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldGT(FieldID, id))
}
// IDGTE applies the GTE predicate on the ID field.
func IDGTE(id uuid.UUID) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldGTE(FieldID, id))
}
// IDLT applies the LT predicate on the ID field.
func IDLT(id uuid.UUID) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldLT(FieldID, id))
}
// IDLTE applies the LTE predicate on the ID field.
func IDLTE(id uuid.UUID) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldLTE(FieldID, id))
}
// IsRemote applies equality check predicate on the "isRemote" field. It's identical to IsRemoteEQ.
func IsRemote(v bool) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldEQ(FieldIsRemote, v))
}
// URI applies equality check predicate on the "uri" field. It's identical to URIEQ.
func URI(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldEQ(FieldURI, v))
}
// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
func CreatedAt(v time.Time) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldEQ(FieldCreatedAt, v))
}
// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ.
func UpdatedAt(v time.Time) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldEQ(FieldUpdatedAt, v))
}
// Name applies equality check predicate on the "name" field. It's identical to NameEQ.
func Name(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldEQ(FieldName, v))
}
// Description applies equality check predicate on the "description" field. It's identical to DescriptionEQ.
func Description(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldEQ(FieldDescription, v))
}
// Version applies equality check predicate on the "version" field. It's identical to VersionEQ.
func Version(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldEQ(FieldVersion, v))
}
// IsRemoteEQ applies the EQ predicate on the "isRemote" field.
func IsRemoteEQ(v bool) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldEQ(FieldIsRemote, v))
}
// IsRemoteNEQ applies the NEQ predicate on the "isRemote" field.
func IsRemoteNEQ(v bool) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldNEQ(FieldIsRemote, v))
}
// URIEQ applies the EQ predicate on the "uri" field.
func URIEQ(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldEQ(FieldURI, v))
}
// URINEQ applies the NEQ predicate on the "uri" field.
func URINEQ(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldNEQ(FieldURI, v))
}
// URIIn applies the In predicate on the "uri" field.
func URIIn(vs ...string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldIn(FieldURI, vs...))
}
// URINotIn applies the NotIn predicate on the "uri" field.
func URINotIn(vs ...string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldNotIn(FieldURI, vs...))
}
// URIGT applies the GT predicate on the "uri" field.
func URIGT(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldGT(FieldURI, v))
}
// URIGTE applies the GTE predicate on the "uri" field.
func URIGTE(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldGTE(FieldURI, v))
}
// URILT applies the LT predicate on the "uri" field.
func URILT(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldLT(FieldURI, v))
}
// URILTE applies the LTE predicate on the "uri" field.
func URILTE(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldLTE(FieldURI, v))
}
// URIContains applies the Contains predicate on the "uri" field.
func URIContains(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldContains(FieldURI, v))
}
// URIHasPrefix applies the HasPrefix predicate on the "uri" field.
func URIHasPrefix(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldHasPrefix(FieldURI, v))
}
// URIHasSuffix applies the HasSuffix predicate on the "uri" field.
func URIHasSuffix(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldHasSuffix(FieldURI, v))
}
// URIEqualFold applies the EqualFold predicate on the "uri" field.
func URIEqualFold(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldEqualFold(FieldURI, v))
}
// URIContainsFold applies the ContainsFold predicate on the "uri" field.
func URIContainsFold(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldContainsFold(FieldURI, v))
}
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
func CreatedAtEQ(v time.Time) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldEQ(FieldCreatedAt, v))
}
// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
func CreatedAtNEQ(v time.Time) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldNEQ(FieldCreatedAt, v))
}
// CreatedAtIn applies the In predicate on the "created_at" field.
func CreatedAtIn(vs ...time.Time) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldIn(FieldCreatedAt, vs...))
}
// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
func CreatedAtNotIn(vs ...time.Time) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldNotIn(FieldCreatedAt, vs...))
}
// CreatedAtGT applies the GT predicate on the "created_at" field.
func CreatedAtGT(v time.Time) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldGT(FieldCreatedAt, v))
}
// CreatedAtGTE applies the GTE predicate on the "created_at" field.
func CreatedAtGTE(v time.Time) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldGTE(FieldCreatedAt, v))
}
// CreatedAtLT applies the LT predicate on the "created_at" field.
func CreatedAtLT(v time.Time) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldLT(FieldCreatedAt, v))
}
// CreatedAtLTE applies the LTE predicate on the "created_at" field.
func CreatedAtLTE(v time.Time) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldLTE(FieldCreatedAt, v))
}
// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
func UpdatedAtEQ(v time.Time) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldEQ(FieldUpdatedAt, v))
}
// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
func UpdatedAtNEQ(v time.Time) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldNEQ(FieldUpdatedAt, v))
}
// UpdatedAtIn applies the In predicate on the "updated_at" field.
func UpdatedAtIn(vs ...time.Time) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldIn(FieldUpdatedAt, vs...))
}
// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
func UpdatedAtNotIn(vs ...time.Time) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldNotIn(FieldUpdatedAt, vs...))
}
// UpdatedAtGT applies the GT predicate on the "updated_at" field.
func UpdatedAtGT(v time.Time) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldGT(FieldUpdatedAt, v))
}
// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
func UpdatedAtGTE(v time.Time) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldGTE(FieldUpdatedAt, v))
}
// UpdatedAtLT applies the LT predicate on the "updated_at" field.
func UpdatedAtLT(v time.Time) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldLT(FieldUpdatedAt, v))
}
// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
func UpdatedAtLTE(v time.Time) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldLTE(FieldUpdatedAt, v))
}
// NameEQ applies the EQ predicate on the "name" field.
func NameEQ(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldEQ(FieldName, v))
}
// NameNEQ applies the NEQ predicate on the "name" field.
func NameNEQ(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldNEQ(FieldName, v))
}
// NameIn applies the In predicate on the "name" field.
func NameIn(vs ...string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldIn(FieldName, vs...))
}
// NameNotIn applies the NotIn predicate on the "name" field.
func NameNotIn(vs ...string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldNotIn(FieldName, vs...))
}
// NameGT applies the GT predicate on the "name" field.
func NameGT(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldGT(FieldName, v))
}
// NameGTE applies the GTE predicate on the "name" field.
func NameGTE(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldGTE(FieldName, v))
}
// NameLT applies the LT predicate on the "name" field.
func NameLT(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldLT(FieldName, v))
}
// NameLTE applies the LTE predicate on the "name" field.
func NameLTE(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldLTE(FieldName, v))
}
// NameContains applies the Contains predicate on the "name" field.
func NameContains(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldContains(FieldName, v))
}
// NameHasPrefix applies the HasPrefix predicate on the "name" field.
func NameHasPrefix(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldHasPrefix(FieldName, v))
}
// NameHasSuffix applies the HasSuffix predicate on the "name" field.
func NameHasSuffix(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldHasSuffix(FieldName, v))
}
// NameEqualFold applies the EqualFold predicate on the "name" field.
func NameEqualFold(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldEqualFold(FieldName, v))
}
// NameContainsFold applies the ContainsFold predicate on the "name" field.
func NameContainsFold(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldContainsFold(FieldName, v))
}
// DescriptionEQ applies the EQ predicate on the "description" field.
func DescriptionEQ(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldEQ(FieldDescription, v))
}
// DescriptionNEQ applies the NEQ predicate on the "description" field.
func DescriptionNEQ(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldNEQ(FieldDescription, v))
}
// DescriptionIn applies the In predicate on the "description" field.
func DescriptionIn(vs ...string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldIn(FieldDescription, vs...))
}
// DescriptionNotIn applies the NotIn predicate on the "description" field.
func DescriptionNotIn(vs ...string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldNotIn(FieldDescription, vs...))
}
// DescriptionGT applies the GT predicate on the "description" field.
func DescriptionGT(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldGT(FieldDescription, v))
}
// DescriptionGTE applies the GTE predicate on the "description" field.
func DescriptionGTE(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldGTE(FieldDescription, v))
}
// DescriptionLT applies the LT predicate on the "description" field.
func DescriptionLT(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldLT(FieldDescription, v))
}
// DescriptionLTE applies the LTE predicate on the "description" field.
func DescriptionLTE(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldLTE(FieldDescription, v))
}
// DescriptionContains applies the Contains predicate on the "description" field.
func DescriptionContains(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldContains(FieldDescription, v))
}
// DescriptionHasPrefix applies the HasPrefix predicate on the "description" field.
func DescriptionHasPrefix(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldHasPrefix(FieldDescription, v))
}
// DescriptionHasSuffix applies the HasSuffix predicate on the "description" field.
func DescriptionHasSuffix(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldHasSuffix(FieldDescription, v))
}
// DescriptionIsNil applies the IsNil predicate on the "description" field.
func DescriptionIsNil() predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldIsNull(FieldDescription))
}
// DescriptionNotNil applies the NotNil predicate on the "description" field.
func DescriptionNotNil() predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldNotNull(FieldDescription))
}
// DescriptionEqualFold applies the EqualFold predicate on the "description" field.
func DescriptionEqualFold(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldEqualFold(FieldDescription, v))
}
// DescriptionContainsFold applies the ContainsFold predicate on the "description" field.
func DescriptionContainsFold(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldContainsFold(FieldDescription, v))
}
// VersionEQ applies the EQ predicate on the "version" field.
func VersionEQ(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldEQ(FieldVersion, v))
}
// VersionNEQ applies the NEQ predicate on the "version" field.
func VersionNEQ(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldNEQ(FieldVersion, v))
}
// VersionIn applies the In predicate on the "version" field.
func VersionIn(vs ...string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldIn(FieldVersion, vs...))
}
// VersionNotIn applies the NotIn predicate on the "version" field.
func VersionNotIn(vs ...string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldNotIn(FieldVersion, vs...))
}
// VersionGT applies the GT predicate on the "version" field.
func VersionGT(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldGT(FieldVersion, v))
}
// VersionGTE applies the GTE predicate on the "version" field.
func VersionGTE(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldGTE(FieldVersion, v))
}
// VersionLT applies the LT predicate on the "version" field.
func VersionLT(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldLT(FieldVersion, v))
}
// VersionLTE applies the LTE predicate on the "version" field.
func VersionLTE(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldLTE(FieldVersion, v))
}
// VersionContains applies the Contains predicate on the "version" field.
func VersionContains(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldContains(FieldVersion, v))
}
// VersionHasPrefix applies the HasPrefix predicate on the "version" field.
func VersionHasPrefix(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldHasPrefix(FieldVersion, v))
}
// VersionHasSuffix applies the HasSuffix predicate on the "version" field.
func VersionHasSuffix(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldHasSuffix(FieldVersion, v))
}
// VersionEqualFold applies the EqualFold predicate on the "version" field.
func VersionEqualFold(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldEqualFold(FieldVersion, v))
}
// VersionContainsFold applies the ContainsFold predicate on the "version" field.
func VersionContainsFold(v string) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.FieldContainsFold(FieldVersion, v))
}
// HasFollower applies the HasEdge predicate on the "follower" edge.
func HasFollower() predicate.ServerMetadata {
return predicate.ServerMetadata(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, FollowerTable, FollowerColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasFollowerWith applies the HasEdge predicate on the "follower" edge with a given conditions (other predicates).
func HasFollowerWith(preds ...predicate.User) predicate.ServerMetadata {
return predicate.ServerMetadata(func(s *sql.Selector) {
step := newFollowerStep()
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
p(s)
}
})
})
}
// HasFollowee applies the HasEdge predicate on the "followee" edge.
func HasFollowee() predicate.ServerMetadata {
return predicate.ServerMetadata(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, FolloweeTable, FolloweeColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasFolloweeWith applies the HasEdge predicate on the "followee" edge with a given conditions (other predicates).
func HasFolloweeWith(preds ...predicate.User) predicate.ServerMetadata {
return predicate.ServerMetadata(func(s *sql.Selector) {
step := newFolloweeStep()
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.ServerMetadata) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.AndPredicates(predicates...))
}
// Or groups predicates with the OR operator between them.
func Or(predicates ...predicate.ServerMetadata) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.OrPredicates(predicates...))
}
// Not applies the not operator on the given predicate.
func Not(p predicate.ServerMetadata) predicate.ServerMetadata {
return predicate.ServerMetadata(sql.NotPredicates(p))
}

File diff suppressed because it is too large Load diff

View file

@ -1,88 +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"
"github.com/lysand-org/versia-go/ent/predicate"
"github.com/lysand-org/versia-go/ent/servermetadata"
)
// ServerMetadataDelete is the builder for deleting a ServerMetadata entity.
type ServerMetadataDelete struct {
config
hooks []Hook
mutation *ServerMetadataMutation
}
// Where appends a list predicates to the ServerMetadataDelete builder.
func (smd *ServerMetadataDelete) Where(ps ...predicate.ServerMetadata) *ServerMetadataDelete {
smd.mutation.Where(ps...)
return smd
}
// Exec executes the deletion query and returns how many vertices were deleted.
func (smd *ServerMetadataDelete) Exec(ctx context.Context) (int, error) {
return withHooks(ctx, smd.sqlExec, smd.mutation, smd.hooks)
}
// ExecX is like Exec, but panics if an error occurs.
func (smd *ServerMetadataDelete) ExecX(ctx context.Context) int {
n, err := smd.Exec(ctx)
if err != nil {
panic(err)
}
return n
}
func (smd *ServerMetadataDelete) sqlExec(ctx context.Context) (int, error) {
_spec := sqlgraph.NewDeleteSpec(servermetadata.Table, sqlgraph.NewFieldSpec(servermetadata.FieldID, field.TypeUUID))
if ps := smd.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
affected, err := sqlgraph.DeleteNodes(ctx, smd.driver, _spec)
if err != nil && sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
smd.mutation.done = true
return affected, err
}
// ServerMetadataDeleteOne is the builder for deleting a single ServerMetadata entity.
type ServerMetadataDeleteOne struct {
smd *ServerMetadataDelete
}
// Where appends a list predicates to the ServerMetadataDelete builder.
func (smdo *ServerMetadataDeleteOne) Where(ps ...predicate.ServerMetadata) *ServerMetadataDeleteOne {
smdo.smd.mutation.Where(ps...)
return smdo
}
// Exec executes the deletion query.
func (smdo *ServerMetadataDeleteOne) Exec(ctx context.Context) error {
n, err := smdo.smd.Exec(ctx)
switch {
case err != nil:
return err
case n == 0:
return &NotFoundError{servermetadata.Label}
default:
return nil
}
}
// ExecX is like Exec, but panics if an error occurs.
func (smdo *ServerMetadataDeleteOne) ExecX(ctx context.Context) {
if err := smdo.Exec(ctx); err != nil {
panic(err)
}
}

View file

@ -1,688 +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"
"github.com/google/uuid"
"github.com/lysand-org/versia-go/ent/predicate"
"github.com/lysand-org/versia-go/ent/servermetadata"
"github.com/lysand-org/versia-go/ent/user"
)
// ServerMetadataQuery is the builder for querying ServerMetadata entities.
type ServerMetadataQuery struct {
config
ctx *QueryContext
order []servermetadata.OrderOption
inters []Interceptor
predicates []predicate.ServerMetadata
withFollower *UserQuery
withFollowee *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 ServerMetadataQuery builder.
func (smq *ServerMetadataQuery) Where(ps ...predicate.ServerMetadata) *ServerMetadataQuery {
smq.predicates = append(smq.predicates, ps...)
return smq
}
// Limit the number of records to be returned by this query.
func (smq *ServerMetadataQuery) Limit(limit int) *ServerMetadataQuery {
smq.ctx.Limit = &limit
return smq
}
// Offset to start from.
func (smq *ServerMetadataQuery) Offset(offset int) *ServerMetadataQuery {
smq.ctx.Offset = &offset
return smq
}
// 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 (smq *ServerMetadataQuery) Unique(unique bool) *ServerMetadataQuery {
smq.ctx.Unique = &unique
return smq
}
// Order specifies how the records should be ordered.
func (smq *ServerMetadataQuery) Order(o ...servermetadata.OrderOption) *ServerMetadataQuery {
smq.order = append(smq.order, o...)
return smq
}
// QueryFollower chains the current query on the "follower" edge.
func (smq *ServerMetadataQuery) QueryFollower() *UserQuery {
query := (&UserClient{config: smq.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := smq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := smq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(servermetadata.Table, servermetadata.FieldID, selector),
sqlgraph.To(user.Table, user.FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, servermetadata.FollowerTable, servermetadata.FollowerColumn),
)
fromU = sqlgraph.SetNeighbors(smq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// QueryFollowee chains the current query on the "followee" edge.
func (smq *ServerMetadataQuery) QueryFollowee() *UserQuery {
query := (&UserClient{config: smq.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := smq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := smq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(servermetadata.Table, servermetadata.FieldID, selector),
sqlgraph.To(user.Table, user.FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, servermetadata.FolloweeTable, servermetadata.FolloweeColumn),
)
fromU = sqlgraph.SetNeighbors(smq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// First returns the first ServerMetadata entity from the query.
// Returns a *NotFoundError when no ServerMetadata was found.
func (smq *ServerMetadataQuery) First(ctx context.Context) (*ServerMetadata, error) {
nodes, err := smq.Limit(1).All(setContextOp(ctx, smq.ctx, "First"))
if err != nil {
return nil, err
}
if len(nodes) == 0 {
return nil, &NotFoundError{servermetadata.Label}
}
return nodes[0], nil
}
// FirstX is like First, but panics if an error occurs.
func (smq *ServerMetadataQuery) FirstX(ctx context.Context) *ServerMetadata {
node, err := smq.First(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return node
}
// FirstID returns the first ServerMetadata ID from the query.
// Returns a *NotFoundError when no ServerMetadata ID was found.
func (smq *ServerMetadataQuery) FirstID(ctx context.Context) (id uuid.UUID, err error) {
var ids []uuid.UUID
if ids, err = smq.Limit(1).IDs(setContextOp(ctx, smq.ctx, "FirstID")); err != nil {
return
}
if len(ids) == 0 {
err = &NotFoundError{servermetadata.Label}
return
}
return ids[0], nil
}
// FirstIDX is like FirstID, but panics if an error occurs.
func (smq *ServerMetadataQuery) FirstIDX(ctx context.Context) uuid.UUID {
id, err := smq.FirstID(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return id
}
// Only returns a single ServerMetadata entity found by the query, ensuring it only returns one.
// Returns a *NotSingularError when more than one ServerMetadata entity is found.
// Returns a *NotFoundError when no ServerMetadata entities are found.
func (smq *ServerMetadataQuery) Only(ctx context.Context) (*ServerMetadata, error) {
nodes, err := smq.Limit(2).All(setContextOp(ctx, smq.ctx, "Only"))
if err != nil {
return nil, err
}
switch len(nodes) {
case 1:
return nodes[0], nil
case 0:
return nil, &NotFoundError{servermetadata.Label}
default:
return nil, &NotSingularError{servermetadata.Label}
}
}
// OnlyX is like Only, but panics if an error occurs.
func (smq *ServerMetadataQuery) OnlyX(ctx context.Context) *ServerMetadata {
node, err := smq.Only(ctx)
if err != nil {
panic(err)
}
return node
}
// OnlyID is like Only, but returns the only ServerMetadata ID in the query.
// Returns a *NotSingularError when more than one ServerMetadata ID is found.
// Returns a *NotFoundError when no entities are found.
func (smq *ServerMetadataQuery) OnlyID(ctx context.Context) (id uuid.UUID, err error) {
var ids []uuid.UUID
if ids, err = smq.Limit(2).IDs(setContextOp(ctx, smq.ctx, "OnlyID")); err != nil {
return
}
switch len(ids) {
case 1:
id = ids[0]
case 0:
err = &NotFoundError{servermetadata.Label}
default:
err = &NotSingularError{servermetadata.Label}
}
return
}
// OnlyIDX is like OnlyID, but panics if an error occurs.
func (smq *ServerMetadataQuery) OnlyIDX(ctx context.Context) uuid.UUID {
id, err := smq.OnlyID(ctx)
if err != nil {
panic(err)
}
return id
}
// All executes the query and returns a list of ServerMetadataSlice.
func (smq *ServerMetadataQuery) All(ctx context.Context) ([]*ServerMetadata, error) {
ctx = setContextOp(ctx, smq.ctx, "All")
if err := smq.prepareQuery(ctx); err != nil {
return nil, err
}
qr := querierAll[[]*ServerMetadata, *ServerMetadataQuery]()
return withInterceptors[[]*ServerMetadata](ctx, smq, qr, smq.inters)
}
// AllX is like All, but panics if an error occurs.
func (smq *ServerMetadataQuery) AllX(ctx context.Context) []*ServerMetadata {
nodes, err := smq.All(ctx)
if err != nil {
panic(err)
}
return nodes
}
// IDs executes the query and returns a list of ServerMetadata IDs.
func (smq *ServerMetadataQuery) IDs(ctx context.Context) (ids []uuid.UUID, err error) {
if smq.ctx.Unique == nil && smq.path != nil {
smq.Unique(true)
}
ctx = setContextOp(ctx, smq.ctx, "IDs")
if err = smq.Select(servermetadata.FieldID).Scan(ctx, &ids); err != nil {
return nil, err
}
return ids, nil
}
// IDsX is like IDs, but panics if an error occurs.
func (smq *ServerMetadataQuery) IDsX(ctx context.Context) []uuid.UUID {
ids, err := smq.IDs(ctx)
if err != nil {
panic(err)
}
return ids
}
// Count returns the count of the given query.
func (smq *ServerMetadataQuery) Count(ctx context.Context) (int, error) {
ctx = setContextOp(ctx, smq.ctx, "Count")
if err := smq.prepareQuery(ctx); err != nil {
return 0, err
}
return withInterceptors[int](ctx, smq, querierCount[*ServerMetadataQuery](), smq.inters)
}
// CountX is like Count, but panics if an error occurs.
func (smq *ServerMetadataQuery) CountX(ctx context.Context) int {
count, err := smq.Count(ctx)
if err != nil {
panic(err)
}
return count
}
// Exist returns true if the query has elements in the graph.
func (smq *ServerMetadataQuery) Exist(ctx context.Context) (bool, error) {
ctx = setContextOp(ctx, smq.ctx, "Exist")
switch _, err := smq.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 (smq *ServerMetadataQuery) ExistX(ctx context.Context) bool {
exist, err := smq.Exist(ctx)
if err != nil {
panic(err)
}
return exist
}
// Clone returns a duplicate of the ServerMetadataQuery builder, including all associated steps. It can be
// used to prepare common query builders and use them differently after the clone is made.
func (smq *ServerMetadataQuery) Clone() *ServerMetadataQuery {
if smq == nil {
return nil
}
return &ServerMetadataQuery{
config: smq.config,
ctx: smq.ctx.Clone(),
order: append([]servermetadata.OrderOption{}, smq.order...),
inters: append([]Interceptor{}, smq.inters...),
predicates: append([]predicate.ServerMetadata{}, smq.predicates...),
withFollower: smq.withFollower.Clone(),
withFollowee: smq.withFollowee.Clone(),
// clone intermediate query.
sql: smq.sql.Clone(),
path: smq.path,
}
}
// WithFollower tells the query-builder to eager-load the nodes that are connected to
// the "follower" edge. The optional arguments are used to configure the query builder of the edge.
func (smq *ServerMetadataQuery) WithFollower(opts ...func(*UserQuery)) *ServerMetadataQuery {
query := (&UserClient{config: smq.config}).Query()
for _, opt := range opts {
opt(query)
}
smq.withFollower = query
return smq
}
// WithFollowee tells the query-builder to eager-load the nodes that are connected to
// the "followee" edge. The optional arguments are used to configure the query builder of the edge.
func (smq *ServerMetadataQuery) WithFollowee(opts ...func(*UserQuery)) *ServerMetadataQuery {
query := (&UserClient{config: smq.config}).Query()
for _, opt := range opts {
opt(query)
}
smq.withFollowee = query
return smq
}
// 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 {
// IsRemote bool `json:"isRemote,omitempty"`
// Count int `json:"count,omitempty"`
// }
//
// client.ServerMetadata.Query().
// GroupBy(servermetadata.FieldIsRemote).
// Aggregate(ent.Count()).
// Scan(ctx, &v)
func (smq *ServerMetadataQuery) GroupBy(field string, fields ...string) *ServerMetadataGroupBy {
smq.ctx.Fields = append([]string{field}, fields...)
grbuild := &ServerMetadataGroupBy{build: smq}
grbuild.flds = &smq.ctx.Fields
grbuild.label = servermetadata.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 {
// IsRemote bool `json:"isRemote,omitempty"`
// }
//
// client.ServerMetadata.Query().
// Select(servermetadata.FieldIsRemote).
// Scan(ctx, &v)
func (smq *ServerMetadataQuery) Select(fields ...string) *ServerMetadataSelect {
smq.ctx.Fields = append(smq.ctx.Fields, fields...)
sbuild := &ServerMetadataSelect{ServerMetadataQuery: smq}
sbuild.label = servermetadata.Label
sbuild.flds, sbuild.scan = &smq.ctx.Fields, sbuild.Scan
return sbuild
}
// Aggregate returns a ServerMetadataSelect configured with the given aggregations.
func (smq *ServerMetadataQuery) Aggregate(fns ...AggregateFunc) *ServerMetadataSelect {
return smq.Select().Aggregate(fns...)
}
func (smq *ServerMetadataQuery) prepareQuery(ctx context.Context) error {
for _, inter := range smq.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, smq); err != nil {
return err
}
}
}
for _, f := range smq.ctx.Fields {
if !servermetadata.ValidColumn(f) {
return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
}
}
if smq.path != nil {
prev, err := smq.path(ctx)
if err != nil {
return err
}
smq.sql = prev
}
return nil
}
func (smq *ServerMetadataQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*ServerMetadata, error) {
var (
nodes = []*ServerMetadata{}
withFKs = smq.withFKs
_spec = smq.querySpec()
loadedTypes = [2]bool{
smq.withFollower != nil,
smq.withFollowee != nil,
}
)
if smq.withFollower != nil || smq.withFollowee != nil {
withFKs = true
}
if withFKs {
_spec.Node.Columns = append(_spec.Node.Columns, servermetadata.ForeignKeys...)
}
_spec.ScanValues = func(columns []string) ([]any, error) {
return (*ServerMetadata).scanValues(nil, columns)
}
_spec.Assign = func(columns []string, values []any) error {
node := &ServerMetadata{config: smq.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, smq.driver, _spec); err != nil {
return nil, err
}
if len(nodes) == 0 {
return nodes, nil
}
if query := smq.withFollower; query != nil {
if err := smq.loadFollower(ctx, query, nodes, nil,
func(n *ServerMetadata, e *User) { n.Edges.Follower = e }); err != nil {
return nil, err
}
}
if query := smq.withFollowee; query != nil {
if err := smq.loadFollowee(ctx, query, nodes, nil,
func(n *ServerMetadata, e *User) { n.Edges.Followee = e }); err != nil {
return nil, err
}
}
return nodes, nil
}
func (smq *ServerMetadataQuery) loadFollower(ctx context.Context, query *UserQuery, nodes []*ServerMetadata, init func(*ServerMetadata), assign func(*ServerMetadata, *User)) error {
ids := make([]uuid.UUID, 0, len(nodes))
nodeids := make(map[uuid.UUID][]*ServerMetadata)
for i := range nodes {
if nodes[i].server_metadata_follower == nil {
continue
}
fk := *nodes[i].server_metadata_follower
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 "server_metadata_follower" returned %v`, n.ID)
}
for i := range nodes {
assign(nodes[i], n)
}
}
return nil
}
func (smq *ServerMetadataQuery) loadFollowee(ctx context.Context, query *UserQuery, nodes []*ServerMetadata, init func(*ServerMetadata), assign func(*ServerMetadata, *User)) error {
ids := make([]uuid.UUID, 0, len(nodes))
nodeids := make(map[uuid.UUID][]*ServerMetadata)
for i := range nodes {
if nodes[i].server_metadata_followee == nil {
continue
}
fk := *nodes[i].server_metadata_followee
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 "server_metadata_followee" returned %v`, n.ID)
}
for i := range nodes {
assign(nodes[i], n)
}
}
return nil
}
func (smq *ServerMetadataQuery) sqlCount(ctx context.Context) (int, error) {
_spec := smq.querySpec()
_spec.Node.Columns = smq.ctx.Fields
if len(smq.ctx.Fields) > 0 {
_spec.Unique = smq.ctx.Unique != nil && *smq.ctx.Unique
}
return sqlgraph.CountNodes(ctx, smq.driver, _spec)
}
func (smq *ServerMetadataQuery) querySpec() *sqlgraph.QuerySpec {
_spec := sqlgraph.NewQuerySpec(servermetadata.Table, servermetadata.Columns, sqlgraph.NewFieldSpec(servermetadata.FieldID, field.TypeUUID))
_spec.From = smq.sql
if unique := smq.ctx.Unique; unique != nil {
_spec.Unique = *unique
} else if smq.path != nil {
_spec.Unique = true
}
if fields := smq.ctx.Fields; len(fields) > 0 {
_spec.Node.Columns = make([]string, 0, len(fields))
_spec.Node.Columns = append(_spec.Node.Columns, servermetadata.FieldID)
for i := range fields {
if fields[i] != servermetadata.FieldID {
_spec.Node.Columns = append(_spec.Node.Columns, fields[i])
}
}
}
if ps := smq.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if limit := smq.ctx.Limit; limit != nil {
_spec.Limit = *limit
}
if offset := smq.ctx.Offset; offset != nil {
_spec.Offset = *offset
}
if ps := smq.order; len(ps) > 0 {
_spec.Order = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
return _spec
}
func (smq *ServerMetadataQuery) sqlQuery(ctx context.Context) *sql.Selector {
builder := sql.Dialect(smq.driver.Dialect())
t1 := builder.Table(servermetadata.Table)
columns := smq.ctx.Fields
if len(columns) == 0 {
columns = servermetadata.Columns
}
selector := builder.Select(t1.Columns(columns...)...).From(t1)
if smq.sql != nil {
selector = smq.sql
selector.Select(selector.Columns(columns...)...)
}
if smq.ctx.Unique != nil && *smq.ctx.Unique {
selector.Distinct()
}
for _, p := range smq.predicates {
p(selector)
}
for _, p := range smq.order {
p(selector)
}
if offset := smq.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 := smq.ctx.Limit; limit != nil {
selector.Limit(*limit)
}
return selector
}
// ServerMetadataGroupBy is the group-by builder for ServerMetadata entities.
type ServerMetadataGroupBy struct {
selector
build *ServerMetadataQuery
}
// Aggregate adds the given aggregation functions to the group-by query.
func (smgb *ServerMetadataGroupBy) Aggregate(fns ...AggregateFunc) *ServerMetadataGroupBy {
smgb.fns = append(smgb.fns, fns...)
return smgb
}
// Scan applies the selector query and scans the result into the given value.
func (smgb *ServerMetadataGroupBy) Scan(ctx context.Context, v any) error {
ctx = setContextOp(ctx, smgb.build.ctx, "GroupBy")
if err := smgb.build.prepareQuery(ctx); err != nil {
return err
}
return scanWithInterceptors[*ServerMetadataQuery, *ServerMetadataGroupBy](ctx, smgb.build, smgb, smgb.build.inters, v)
}
func (smgb *ServerMetadataGroupBy) sqlScan(ctx context.Context, root *ServerMetadataQuery, v any) error {
selector := root.sqlQuery(ctx).Select()
aggregation := make([]string, 0, len(smgb.fns))
for _, fn := range smgb.fns {
aggregation = append(aggregation, fn(selector))
}
if len(selector.SelectedColumns()) == 0 {
columns := make([]string, 0, len(*smgb.flds)+len(smgb.fns))
for _, f := range *smgb.flds {
columns = append(columns, selector.C(f))
}
columns = append(columns, aggregation...)
selector.Select(columns...)
}
selector.GroupBy(selector.Columns(*smgb.flds...)...)
if err := selector.Err(); err != nil {
return err
}
rows := &sql.Rows{}
query, args := selector.Query()
if err := smgb.build.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}
// ServerMetadataSelect is the builder for selecting fields of ServerMetadata entities.
type ServerMetadataSelect struct {
*ServerMetadataQuery
selector
}
// Aggregate adds the given aggregation functions to the selector query.
func (sms *ServerMetadataSelect) Aggregate(fns ...AggregateFunc) *ServerMetadataSelect {
sms.fns = append(sms.fns, fns...)
return sms
}
// Scan applies the selector query and scans the result into the given value.
func (sms *ServerMetadataSelect) Scan(ctx context.Context, v any) error {
ctx = setContextOp(ctx, sms.ctx, "Select")
if err := sms.prepareQuery(ctx); err != nil {
return err
}
return scanWithInterceptors[*ServerMetadataQuery, *ServerMetadataSelect](ctx, sms.ServerMetadataQuery, sms, sms.inters, v)
}
func (sms *ServerMetadataSelect) sqlScan(ctx context.Context, root *ServerMetadataQuery, v any) error {
selector := root.sqlQuery(ctx)
aggregation := make([]string, 0, len(sms.fns))
for _, fn := range sms.fns {
aggregation = append(aggregation, fn(selector))
}
switch n := len(*sms.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 := sms.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}

View file

@ -1,704 +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/dialect/sql/sqljson"
"entgo.io/ent/schema/field"
"github.com/google/uuid"
"github.com/lysand-org/versia-go/ent/predicate"
"github.com/lysand-org/versia-go/ent/servermetadata"
"github.com/lysand-org/versia-go/ent/user"
"github.com/lysand-org/versia-go/pkg/lysand"
)
// ServerMetadataUpdate is the builder for updating ServerMetadata entities.
type ServerMetadataUpdate struct {
config
hooks []Hook
mutation *ServerMetadataMutation
}
// Where appends a list predicates to the ServerMetadataUpdate builder.
func (smu *ServerMetadataUpdate) Where(ps ...predicate.ServerMetadata) *ServerMetadataUpdate {
smu.mutation.Where(ps...)
return smu
}
// SetIsRemote sets the "isRemote" field.
func (smu *ServerMetadataUpdate) SetIsRemote(b bool) *ServerMetadataUpdate {
smu.mutation.SetIsRemote(b)
return smu
}
// SetNillableIsRemote sets the "isRemote" field if the given value is not nil.
func (smu *ServerMetadataUpdate) SetNillableIsRemote(b *bool) *ServerMetadataUpdate {
if b != nil {
smu.SetIsRemote(*b)
}
return smu
}
// SetURI sets the "uri" field.
func (smu *ServerMetadataUpdate) SetURI(s string) *ServerMetadataUpdate {
smu.mutation.SetURI(s)
return smu
}
// SetNillableURI sets the "uri" field if the given value is not nil.
func (smu *ServerMetadataUpdate) SetNillableURI(s *string) *ServerMetadataUpdate {
if s != nil {
smu.SetURI(*s)
}
return smu
}
// SetExtensions sets the "extensions" field.
func (smu *ServerMetadataUpdate) SetExtensions(l lysand.Extensions) *ServerMetadataUpdate {
smu.mutation.SetExtensions(l)
return smu
}
// SetUpdatedAt sets the "updated_at" field.
func (smu *ServerMetadataUpdate) SetUpdatedAt(t time.Time) *ServerMetadataUpdate {
smu.mutation.SetUpdatedAt(t)
return smu
}
// SetName sets the "name" field.
func (smu *ServerMetadataUpdate) SetName(s string) *ServerMetadataUpdate {
smu.mutation.SetName(s)
return smu
}
// SetNillableName sets the "name" field if the given value is not nil.
func (smu *ServerMetadataUpdate) SetNillableName(s *string) *ServerMetadataUpdate {
if s != nil {
smu.SetName(*s)
}
return smu
}
// SetDescription sets the "description" field.
func (smu *ServerMetadataUpdate) SetDescription(s string) *ServerMetadataUpdate {
smu.mutation.SetDescription(s)
return smu
}
// SetNillableDescription sets the "description" field if the given value is not nil.
func (smu *ServerMetadataUpdate) SetNillableDescription(s *string) *ServerMetadataUpdate {
if s != nil {
smu.SetDescription(*s)
}
return smu
}
// ClearDescription clears the value of the "description" field.
func (smu *ServerMetadataUpdate) ClearDescription() *ServerMetadataUpdate {
smu.mutation.ClearDescription()
return smu
}
// SetVersion sets the "version" field.
func (smu *ServerMetadataUpdate) SetVersion(s string) *ServerMetadataUpdate {
smu.mutation.SetVersion(s)
return smu
}
// SetNillableVersion sets the "version" field if the given value is not nil.
func (smu *ServerMetadataUpdate) SetNillableVersion(s *string) *ServerMetadataUpdate {
if s != nil {
smu.SetVersion(*s)
}
return smu
}
// SetSupportedExtensions sets the "supportedExtensions" field.
func (smu *ServerMetadataUpdate) SetSupportedExtensions(s []string) *ServerMetadataUpdate {
smu.mutation.SetSupportedExtensions(s)
return smu
}
// AppendSupportedExtensions appends s to the "supportedExtensions" field.
func (smu *ServerMetadataUpdate) AppendSupportedExtensions(s []string) *ServerMetadataUpdate {
smu.mutation.AppendSupportedExtensions(s)
return smu
}
// SetFollowerID sets the "follower" edge to the User entity by ID.
func (smu *ServerMetadataUpdate) SetFollowerID(id uuid.UUID) *ServerMetadataUpdate {
smu.mutation.SetFollowerID(id)
return smu
}
// SetFollower sets the "follower" edge to the User entity.
func (smu *ServerMetadataUpdate) SetFollower(u *User) *ServerMetadataUpdate {
return smu.SetFollowerID(u.ID)
}
// SetFolloweeID sets the "followee" edge to the User entity by ID.
func (smu *ServerMetadataUpdate) SetFolloweeID(id uuid.UUID) *ServerMetadataUpdate {
smu.mutation.SetFolloweeID(id)
return smu
}
// SetFollowee sets the "followee" edge to the User entity.
func (smu *ServerMetadataUpdate) SetFollowee(u *User) *ServerMetadataUpdate {
return smu.SetFolloweeID(u.ID)
}
// Mutation returns the ServerMetadataMutation object of the builder.
func (smu *ServerMetadataUpdate) Mutation() *ServerMetadataMutation {
return smu.mutation
}
// ClearFollower clears the "follower" edge to the User entity.
func (smu *ServerMetadataUpdate) ClearFollower() *ServerMetadataUpdate {
smu.mutation.ClearFollower()
return smu
}
// ClearFollowee clears the "followee" edge to the User entity.
func (smu *ServerMetadataUpdate) ClearFollowee() *ServerMetadataUpdate {
smu.mutation.ClearFollowee()
return smu
}
// Save executes the query and returns the number of nodes affected by the update operation.
func (smu *ServerMetadataUpdate) Save(ctx context.Context) (int, error) {
smu.defaults()
return withHooks(ctx, smu.sqlSave, smu.mutation, smu.hooks)
}
// SaveX is like Save, but panics if an error occurs.
func (smu *ServerMetadataUpdate) SaveX(ctx context.Context) int {
affected, err := smu.Save(ctx)
if err != nil {
panic(err)
}
return affected
}
// Exec executes the query.
func (smu *ServerMetadataUpdate) Exec(ctx context.Context) error {
_, err := smu.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (smu *ServerMetadataUpdate) ExecX(ctx context.Context) {
if err := smu.Exec(ctx); err != nil {
panic(err)
}
}
// defaults sets the default values of the builder before save.
func (smu *ServerMetadataUpdate) defaults() {
if _, ok := smu.mutation.UpdatedAt(); !ok {
v := servermetadata.UpdateDefaultUpdatedAt()
smu.mutation.SetUpdatedAt(v)
}
}
// check runs all checks and user-defined validators on the builder.
func (smu *ServerMetadataUpdate) check() error {
if v, ok := smu.mutation.URI(); ok {
if err := servermetadata.URIValidator(v); err != nil {
return &ValidationError{Name: "uri", err: fmt.Errorf(`ent: validator failed for field "ServerMetadata.uri": %w`, err)}
}
}
if v, ok := smu.mutation.Name(); ok {
if err := servermetadata.NameValidator(v); err != nil {
return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "ServerMetadata.name": %w`, err)}
}
}
if v, ok := smu.mutation.Version(); ok {
if err := servermetadata.VersionValidator(v); err != nil {
return &ValidationError{Name: "version", err: fmt.Errorf(`ent: validator failed for field "ServerMetadata.version": %w`, err)}
}
}
if _, ok := smu.mutation.FollowerID(); smu.mutation.FollowerCleared() && !ok {
return errors.New(`ent: clearing a required unique edge "ServerMetadata.follower"`)
}
if _, ok := smu.mutation.FolloweeID(); smu.mutation.FolloweeCleared() && !ok {
return errors.New(`ent: clearing a required unique edge "ServerMetadata.followee"`)
}
return nil
}
func (smu *ServerMetadataUpdate) sqlSave(ctx context.Context) (n int, err error) {
if err := smu.check(); err != nil {
return n, err
}
_spec := sqlgraph.NewUpdateSpec(servermetadata.Table, servermetadata.Columns, sqlgraph.NewFieldSpec(servermetadata.FieldID, field.TypeUUID))
if ps := smu.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if value, ok := smu.mutation.IsRemote(); ok {
_spec.SetField(servermetadata.FieldIsRemote, field.TypeBool, value)
}
if value, ok := smu.mutation.URI(); ok {
_spec.SetField(servermetadata.FieldURI, field.TypeString, value)
}
if value, ok := smu.mutation.Extensions(); ok {
_spec.SetField(servermetadata.FieldExtensions, field.TypeJSON, value)
}
if value, ok := smu.mutation.UpdatedAt(); ok {
_spec.SetField(servermetadata.FieldUpdatedAt, field.TypeTime, value)
}
if value, ok := smu.mutation.Name(); ok {
_spec.SetField(servermetadata.FieldName, field.TypeString, value)
}
if value, ok := smu.mutation.Description(); ok {
_spec.SetField(servermetadata.FieldDescription, field.TypeString, value)
}
if smu.mutation.DescriptionCleared() {
_spec.ClearField(servermetadata.FieldDescription, field.TypeString)
}
if value, ok := smu.mutation.Version(); ok {
_spec.SetField(servermetadata.FieldVersion, field.TypeString, value)
}
if value, ok := smu.mutation.SupportedExtensions(); ok {
_spec.SetField(servermetadata.FieldSupportedExtensions, field.TypeJSON, value)
}
if value, ok := smu.mutation.AppendedSupportedExtensions(); ok {
_spec.AddModifier(func(u *sql.UpdateBuilder) {
sqljson.Append(u, servermetadata.FieldSupportedExtensions, value)
})
}
if smu.mutation.FollowerCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: servermetadata.FollowerTable,
Columns: []string{servermetadata.FollowerColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeUUID),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := smu.mutation.FollowerIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: servermetadata.FollowerTable,
Columns: []string{servermetadata.FollowerColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if smu.mutation.FolloweeCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: servermetadata.FolloweeTable,
Columns: []string{servermetadata.FolloweeColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeUUID),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := smu.mutation.FolloweeIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: servermetadata.FolloweeTable,
Columns: []string{servermetadata.FolloweeColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeUUID),
},
}
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, smu.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{servermetadata.Label}
} else if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
return 0, err
}
smu.mutation.done = true
return n, nil
}
// ServerMetadataUpdateOne is the builder for updating a single ServerMetadata entity.
type ServerMetadataUpdateOne struct {
config
fields []string
hooks []Hook
mutation *ServerMetadataMutation
}
// SetIsRemote sets the "isRemote" field.
func (smuo *ServerMetadataUpdateOne) SetIsRemote(b bool) *ServerMetadataUpdateOne {
smuo.mutation.SetIsRemote(b)
return smuo
}
// SetNillableIsRemote sets the "isRemote" field if the given value is not nil.
func (smuo *ServerMetadataUpdateOne) SetNillableIsRemote(b *bool) *ServerMetadataUpdateOne {
if b != nil {
smuo.SetIsRemote(*b)
}
return smuo
}
// SetURI sets the "uri" field.
func (smuo *ServerMetadataUpdateOne) SetURI(s string) *ServerMetadataUpdateOne {
smuo.mutation.SetURI(s)
return smuo
}
// SetNillableURI sets the "uri" field if the given value is not nil.
func (smuo *ServerMetadataUpdateOne) SetNillableURI(s *string) *ServerMetadataUpdateOne {
if s != nil {
smuo.SetURI(*s)
}
return smuo
}
// SetExtensions sets the "extensions" field.
func (smuo *ServerMetadataUpdateOne) SetExtensions(l lysand.Extensions) *ServerMetadataUpdateOne {
smuo.mutation.SetExtensions(l)
return smuo
}
// SetUpdatedAt sets the "updated_at" field.
func (smuo *ServerMetadataUpdateOne) SetUpdatedAt(t time.Time) *ServerMetadataUpdateOne {
smuo.mutation.SetUpdatedAt(t)
return smuo
}
// SetName sets the "name" field.
func (smuo *ServerMetadataUpdateOne) SetName(s string) *ServerMetadataUpdateOne {
smuo.mutation.SetName(s)
return smuo
}
// SetNillableName sets the "name" field if the given value is not nil.
func (smuo *ServerMetadataUpdateOne) SetNillableName(s *string) *ServerMetadataUpdateOne {
if s != nil {
smuo.SetName(*s)
}
return smuo
}
// SetDescription sets the "description" field.
func (smuo *ServerMetadataUpdateOne) SetDescription(s string) *ServerMetadataUpdateOne {
smuo.mutation.SetDescription(s)
return smuo
}
// SetNillableDescription sets the "description" field if the given value is not nil.
func (smuo *ServerMetadataUpdateOne) SetNillableDescription(s *string) *ServerMetadataUpdateOne {
if s != nil {
smuo.SetDescription(*s)
}
return smuo
}
// ClearDescription clears the value of the "description" field.
func (smuo *ServerMetadataUpdateOne) ClearDescription() *ServerMetadataUpdateOne {
smuo.mutation.ClearDescription()
return smuo
}
// SetVersion sets the "version" field.
func (smuo *ServerMetadataUpdateOne) SetVersion(s string) *ServerMetadataUpdateOne {
smuo.mutation.SetVersion(s)
return smuo
}
// SetNillableVersion sets the "version" field if the given value is not nil.
func (smuo *ServerMetadataUpdateOne) SetNillableVersion(s *string) *ServerMetadataUpdateOne {
if s != nil {
smuo.SetVersion(*s)
}
return smuo
}
// SetSupportedExtensions sets the "supportedExtensions" field.
func (smuo *ServerMetadataUpdateOne) SetSupportedExtensions(s []string) *ServerMetadataUpdateOne {
smuo.mutation.SetSupportedExtensions(s)
return smuo
}
// AppendSupportedExtensions appends s to the "supportedExtensions" field.
func (smuo *ServerMetadataUpdateOne) AppendSupportedExtensions(s []string) *ServerMetadataUpdateOne {
smuo.mutation.AppendSupportedExtensions(s)
return smuo
}
// SetFollowerID sets the "follower" edge to the User entity by ID.
func (smuo *ServerMetadataUpdateOne) SetFollowerID(id uuid.UUID) *ServerMetadataUpdateOne {
smuo.mutation.SetFollowerID(id)
return smuo
}
// SetFollower sets the "follower" edge to the User entity.
func (smuo *ServerMetadataUpdateOne) SetFollower(u *User) *ServerMetadataUpdateOne {
return smuo.SetFollowerID(u.ID)
}
// SetFolloweeID sets the "followee" edge to the User entity by ID.
func (smuo *ServerMetadataUpdateOne) SetFolloweeID(id uuid.UUID) *ServerMetadataUpdateOne {
smuo.mutation.SetFolloweeID(id)
return smuo
}
// SetFollowee sets the "followee" edge to the User entity.
func (smuo *ServerMetadataUpdateOne) SetFollowee(u *User) *ServerMetadataUpdateOne {
return smuo.SetFolloweeID(u.ID)
}
// Mutation returns the ServerMetadataMutation object of the builder.
func (smuo *ServerMetadataUpdateOne) Mutation() *ServerMetadataMutation {
return smuo.mutation
}
// ClearFollower clears the "follower" edge to the User entity.
func (smuo *ServerMetadataUpdateOne) ClearFollower() *ServerMetadataUpdateOne {
smuo.mutation.ClearFollower()
return smuo
}
// ClearFollowee clears the "followee" edge to the User entity.
func (smuo *ServerMetadataUpdateOne) ClearFollowee() *ServerMetadataUpdateOne {
smuo.mutation.ClearFollowee()
return smuo
}
// Where appends a list predicates to the ServerMetadataUpdate builder.
func (smuo *ServerMetadataUpdateOne) Where(ps ...predicate.ServerMetadata) *ServerMetadataUpdateOne {
smuo.mutation.Where(ps...)
return smuo
}
// Select allows selecting one or more fields (columns) of the returned entity.
// The default is selecting all fields defined in the entity schema.
func (smuo *ServerMetadataUpdateOne) Select(field string, fields ...string) *ServerMetadataUpdateOne {
smuo.fields = append([]string{field}, fields...)
return smuo
}
// Save executes the query and returns the updated ServerMetadata entity.
func (smuo *ServerMetadataUpdateOne) Save(ctx context.Context) (*ServerMetadata, error) {
smuo.defaults()
return withHooks(ctx, smuo.sqlSave, smuo.mutation, smuo.hooks)
}
// SaveX is like Save, but panics if an error occurs.
func (smuo *ServerMetadataUpdateOne) SaveX(ctx context.Context) *ServerMetadata {
node, err := smuo.Save(ctx)
if err != nil {
panic(err)
}
return node
}
// Exec executes the query on the entity.
func (smuo *ServerMetadataUpdateOne) Exec(ctx context.Context) error {
_, err := smuo.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (smuo *ServerMetadataUpdateOne) ExecX(ctx context.Context) {
if err := smuo.Exec(ctx); err != nil {
panic(err)
}
}
// defaults sets the default values of the builder before save.
func (smuo *ServerMetadataUpdateOne) defaults() {
if _, ok := smuo.mutation.UpdatedAt(); !ok {
v := servermetadata.UpdateDefaultUpdatedAt()
smuo.mutation.SetUpdatedAt(v)
}
}
// check runs all checks and user-defined validators on the builder.
func (smuo *ServerMetadataUpdateOne) check() error {
if v, ok := smuo.mutation.URI(); ok {
if err := servermetadata.URIValidator(v); err != nil {
return &ValidationError{Name: "uri", err: fmt.Errorf(`ent: validator failed for field "ServerMetadata.uri": %w`, err)}
}
}
if v, ok := smuo.mutation.Name(); ok {
if err := servermetadata.NameValidator(v); err != nil {
return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "ServerMetadata.name": %w`, err)}
}
}
if v, ok := smuo.mutation.Version(); ok {
if err := servermetadata.VersionValidator(v); err != nil {
return &ValidationError{Name: "version", err: fmt.Errorf(`ent: validator failed for field "ServerMetadata.version": %w`, err)}
}
}
if _, ok := smuo.mutation.FollowerID(); smuo.mutation.FollowerCleared() && !ok {
return errors.New(`ent: clearing a required unique edge "ServerMetadata.follower"`)
}
if _, ok := smuo.mutation.FolloweeID(); smuo.mutation.FolloweeCleared() && !ok {
return errors.New(`ent: clearing a required unique edge "ServerMetadata.followee"`)
}
return nil
}
func (smuo *ServerMetadataUpdateOne) sqlSave(ctx context.Context) (_node *ServerMetadata, err error) {
if err := smuo.check(); err != nil {
return _node, err
}
_spec := sqlgraph.NewUpdateSpec(servermetadata.Table, servermetadata.Columns, sqlgraph.NewFieldSpec(servermetadata.FieldID, field.TypeUUID))
id, ok := smuo.mutation.ID()
if !ok {
return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "ServerMetadata.id" for update`)}
}
_spec.Node.ID.Value = id
if fields := smuo.fields; len(fields) > 0 {
_spec.Node.Columns = make([]string, 0, len(fields))
_spec.Node.Columns = append(_spec.Node.Columns, servermetadata.FieldID)
for _, f := range fields {
if !servermetadata.ValidColumn(f) {
return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
}
if f != servermetadata.FieldID {
_spec.Node.Columns = append(_spec.Node.Columns, f)
}
}
}
if ps := smuo.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if value, ok := smuo.mutation.IsRemote(); ok {
_spec.SetField(servermetadata.FieldIsRemote, field.TypeBool, value)
}
if value, ok := smuo.mutation.URI(); ok {
_spec.SetField(servermetadata.FieldURI, field.TypeString, value)
}
if value, ok := smuo.mutation.Extensions(); ok {
_spec.SetField(servermetadata.FieldExtensions, field.TypeJSON, value)
}
if value, ok := smuo.mutation.UpdatedAt(); ok {
_spec.SetField(servermetadata.FieldUpdatedAt, field.TypeTime, value)
}
if value, ok := smuo.mutation.Name(); ok {
_spec.SetField(servermetadata.FieldName, field.TypeString, value)
}
if value, ok := smuo.mutation.Description(); ok {
_spec.SetField(servermetadata.FieldDescription, field.TypeString, value)
}
if smuo.mutation.DescriptionCleared() {
_spec.ClearField(servermetadata.FieldDescription, field.TypeString)
}
if value, ok := smuo.mutation.Version(); ok {
_spec.SetField(servermetadata.FieldVersion, field.TypeString, value)
}
if value, ok := smuo.mutation.SupportedExtensions(); ok {
_spec.SetField(servermetadata.FieldSupportedExtensions, field.TypeJSON, value)
}
if value, ok := smuo.mutation.AppendedSupportedExtensions(); ok {
_spec.AddModifier(func(u *sql.UpdateBuilder) {
sqljson.Append(u, servermetadata.FieldSupportedExtensions, value)
})
}
if smuo.mutation.FollowerCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: servermetadata.FollowerTable,
Columns: []string{servermetadata.FollowerColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeUUID),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := smuo.mutation.FollowerIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: servermetadata.FollowerTable,
Columns: []string{servermetadata.FollowerColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if smuo.mutation.FolloweeCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: servermetadata.FolloweeTable,
Columns: []string{servermetadata.FolloweeColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeUUID),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := smuo.mutation.FolloweeIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: servermetadata.FolloweeTable,
Columns: []string{servermetadata.FolloweeColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
_node = &ServerMetadata{config: smuo.config}
_spec.Assign = _node.assignValues
_spec.ScanValues = _node.scanValues
if err = sqlgraph.UpdateNode(ctx, smuo.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{servermetadata.Label}
} else if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
return nil, err
}
smuo.mutation.done = true
return _node, nil
}

View file

@ -18,10 +18,10 @@ type Tx struct {
Follow *FollowClient
// Image is the client for interacting with the Image builders.
Image *ImageClient
// InstanceMetadata is the client for interacting with the InstanceMetadata builders.
InstanceMetadata *InstanceMetadataClient
// Note is the client for interacting with the Note builders.
Note *NoteClient
// ServerMetadata is the client for interacting with the ServerMetadata builders.
ServerMetadata *ServerMetadataClient
// User is the client for interacting with the User builders.
User *UserClient
@ -158,8 +158,8 @@ func (tx *Tx) init() {
tx.Attachment = NewAttachmentClient(tx.config)
tx.Follow = NewFollowClient(tx.config)
tx.Image = NewImageClient(tx.config)
tx.InstanceMetadata = NewInstanceMetadataClient(tx.config)
tx.Note = NewNoteClient(tx.config)
tx.ServerMetadata = NewServerMetadataClient(tx.config)
tx.User = NewUserClient(tx.config)
}

View file

@ -3,7 +3,6 @@
package ent
import (
"crypto/ed25519"
"encoding/json"
"fmt"
"strings"
@ -41,9 +40,13 @@ type User struct {
// Biography holds the value of the "biography" field.
Biography *string `json:"biography,omitempty"`
// PublicKey holds the value of the "publicKey" field.
PublicKey ed25519.PublicKey `json:"publicKey,omitempty"`
PublicKey []byte `json:"publicKey,omitempty"`
// PublicKeyActor holds the value of the "publicKeyActor" field.
PublicKeyActor string `json:"publicKeyActor,omitempty"`
// PublicKeyAlgorithm holds the value of the "publicKeyAlgorithm" field.
PublicKeyAlgorithm string `json:"publicKeyAlgorithm,omitempty"`
// PrivateKey holds the value of the "privateKey" field.
PrivateKey ed25519.PrivateKey `json:"privateKey,omitempty"`
PrivateKey []byte `json:"privateKey,omitempty"`
// Indexable holds the value of the "indexable" field.
Indexable bool `json:"indexable,omitempty"`
// PrivacyLevel holds the value of the "privacyLevel" field.
@ -78,9 +81,15 @@ type UserEdges struct {
AuthoredNotes []*Note `json:"authoredNotes,omitempty"`
// MentionedNotes holds the value of the mentionedNotes edge.
MentionedNotes []*Note `json:"mentionedNotes,omitempty"`
// Servers holds the value of the servers edge.
Servers []*InstanceMetadata `json:"servers,omitempty"`
// ModeratedServers holds the value of the moderatedServers edge.
ModeratedServers []*InstanceMetadata `json:"moderatedServers,omitempty"`
// AdministeredServers holds the value of the administeredServers edge.
AdministeredServers []*InstanceMetadata `json:"administeredServers,omitempty"`
// loadedTypes holds the information for reporting if a
// type was loaded (or requested) in eager-loading or not.
loadedTypes [4]bool
loadedTypes [7]bool
}
// AvatarImageOrErr returns the AvatarImage value or an error if the edge
@ -123,6 +132,33 @@ func (e UserEdges) MentionedNotesOrErr() ([]*Note, error) {
return nil, &NotLoadedError{edge: "mentionedNotes"}
}
// ServersOrErr returns the Servers value or an error if the edge
// was not loaded in eager-loading.
func (e UserEdges) ServersOrErr() ([]*InstanceMetadata, error) {
if e.loadedTypes[4] {
return e.Servers, nil
}
return nil, &NotLoadedError{edge: "servers"}
}
// ModeratedServersOrErr returns the ModeratedServers value or an error if the edge
// was not loaded in eager-loading.
func (e UserEdges) ModeratedServersOrErr() ([]*InstanceMetadata, error) {
if e.loadedTypes[5] {
return e.ModeratedServers, nil
}
return nil, &NotLoadedError{edge: "moderatedServers"}
}
// AdministeredServersOrErr returns the AdministeredServers value or an error if the edge
// was not loaded in eager-loading.
func (e UserEdges) AdministeredServersOrErr() ([]*InstanceMetadata, error) {
if e.loadedTypes[6] {
return e.AdministeredServers, nil
}
return nil, &NotLoadedError{edge: "administeredServers"}
}
// scanValues returns the types for scanning values from sql.Rows.
func (*User) scanValues(columns []string) ([]any, error) {
values := make([]any, len(columns))
@ -132,7 +168,7 @@ func (*User) scanValues(columns []string) ([]any, error) {
values[i] = new([]byte)
case user.FieldIsRemote, user.FieldIndexable:
values[i] = new(sql.NullBool)
case user.FieldURI, user.FieldUsername, user.FieldDisplayName, user.FieldBiography, user.FieldPrivacyLevel, user.FieldInbox, user.FieldFeatured, user.FieldFollowers, user.FieldFollowing, user.FieldOutbox:
case user.FieldURI, user.FieldUsername, user.FieldDisplayName, user.FieldBiography, user.FieldPublicKeyActor, user.FieldPublicKeyAlgorithm, user.FieldPrivacyLevel, user.FieldInbox, user.FieldFeatured, user.FieldFollowers, user.FieldFollowing, user.FieldOutbox:
values[i] = new(sql.NullString)
case user.FieldCreatedAt, user.FieldUpdatedAt:
values[i] = new(sql.NullTime)
@ -227,6 +263,18 @@ func (u *User) assignValues(columns []string, values []any) error {
} else if value != nil {
u.PublicKey = *value
}
case user.FieldPublicKeyActor:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field publicKeyActor", values[i])
} else if value.Valid {
u.PublicKeyActor = value.String
}
case user.FieldPublicKeyAlgorithm:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field publicKeyAlgorithm", values[i])
} else if value.Valid {
u.PublicKeyAlgorithm = value.String
}
case user.FieldPrivateKey:
if value, ok := values[i].(*[]byte); !ok {
return fmt.Errorf("unexpected type %T for field privateKey", values[i])
@ -330,6 +378,21 @@ func (u *User) QueryMentionedNotes() *NoteQuery {
return NewUserClient(u.config).QueryMentionedNotes(u)
}
// QueryServers queries the "servers" edge of the User entity.
func (u *User) QueryServers() *InstanceMetadataQuery {
return NewUserClient(u.config).QueryServers(u)
}
// QueryModeratedServers queries the "moderatedServers" edge of the User entity.
func (u *User) QueryModeratedServers() *InstanceMetadataQuery {
return NewUserClient(u.config).QueryModeratedServers(u)
}
// QueryAdministeredServers queries the "administeredServers" edge of the User entity.
func (u *User) QueryAdministeredServers() *InstanceMetadataQuery {
return NewUserClient(u.config).QueryAdministeredServers(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.
@ -389,6 +452,12 @@ func (u *User) String() string {
builder.WriteString("publicKey=")
builder.WriteString(fmt.Sprintf("%v", u.PublicKey))
builder.WriteString(", ")
builder.WriteString("publicKeyActor=")
builder.WriteString(u.PublicKeyActor)
builder.WriteString(", ")
builder.WriteString("publicKeyAlgorithm=")
builder.WriteString(u.PublicKeyAlgorithm)
builder.WriteString(", ")
builder.WriteString("privateKey=")
builder.WriteString(fmt.Sprintf("%v", u.PrivateKey))
builder.WriteString(", ")

View file

@ -37,6 +37,10 @@ const (
FieldBiography = "biography"
// FieldPublicKey holds the string denoting the publickey field in the database.
FieldPublicKey = "public_key"
// FieldPublicKeyActor holds the string denoting the publickeyactor field in the database.
FieldPublicKeyActor = "public_key_actor"
// FieldPublicKeyAlgorithm holds the string denoting the publickeyalgorithm field in the database.
FieldPublicKeyAlgorithm = "public_key_algorithm"
// FieldPrivateKey holds the string denoting the privatekey field in the database.
FieldPrivateKey = "private_key"
// FieldIndexable holds the string denoting the indexable field in the database.
@ -63,6 +67,12 @@ const (
EdgeAuthoredNotes = "authoredNotes"
// EdgeMentionedNotes holds the string denoting the mentionednotes edge name in mutations.
EdgeMentionedNotes = "mentionedNotes"
// EdgeServers holds the string denoting the servers edge name in mutations.
EdgeServers = "servers"
// EdgeModeratedServers holds the string denoting the moderatedservers edge name in mutations.
EdgeModeratedServers = "moderatedServers"
// EdgeAdministeredServers holds the string denoting the administeredservers edge name in mutations.
EdgeAdministeredServers = "administeredServers"
// Table holds the table name of the user in the database.
Table = "users"
// AvatarImageTable is the table that holds the avatarImage relation/edge.
@ -91,6 +101,21 @@ const (
// MentionedNotesInverseTable is the table name for the Note entity.
// It exists in this package in order to avoid circular dependency with the "note" package.
MentionedNotesInverseTable = "notes"
// ServersTable is the table that holds the servers relation/edge. The primary key declared below.
ServersTable = "instance_metadata_users"
// ServersInverseTable is the table name for the InstanceMetadata entity.
// It exists in this package in order to avoid circular dependency with the "instancemetadata" package.
ServersInverseTable = "instance_metadata"
// ModeratedServersTable is the table that holds the moderatedServers relation/edge. The primary key declared below.
ModeratedServersTable = "instance_metadata_moderators"
// ModeratedServersInverseTable is the table name for the InstanceMetadata entity.
// It exists in this package in order to avoid circular dependency with the "instancemetadata" package.
ModeratedServersInverseTable = "instance_metadata"
// AdministeredServersTable is the table that holds the administeredServers relation/edge. The primary key declared below.
AdministeredServersTable = "instance_metadata_admins"
// AdministeredServersInverseTable is the table name for the InstanceMetadata entity.
// It exists in this package in order to avoid circular dependency with the "instancemetadata" package.
AdministeredServersInverseTable = "instance_metadata"
)
// Columns holds all SQL columns for user fields.
@ -106,6 +131,8 @@ var Columns = []string{
FieldDisplayName,
FieldBiography,
FieldPublicKey,
FieldPublicKeyActor,
FieldPublicKeyAlgorithm,
FieldPrivateKey,
FieldIndexable,
FieldPrivacyLevel,
@ -128,6 +155,15 @@ var (
// MentionedNotesPrimaryKey and MentionedNotesColumn2 are the table columns denoting the
// primary key for the mentionedNotes relation (M2M).
MentionedNotesPrimaryKey = []string{"note_id", "user_id"}
// ServersPrimaryKey and ServersColumn2 are the table columns denoting the
// primary key for the servers relation (M2M).
ServersPrimaryKey = []string{"instance_metadata_id", "user_id"}
// ModeratedServersPrimaryKey and ModeratedServersColumn2 are the table columns denoting the
// primary key for the moderatedServers relation (M2M).
ModeratedServersPrimaryKey = []string{"instance_metadata_id", "user_id"}
// AdministeredServersPrimaryKey and AdministeredServersColumn2 are the table columns denoting the
// primary key for the administeredServers relation (M2M).
AdministeredServersPrimaryKey = []string{"instance_metadata_id", "user_id"}
)
// ValidColumn reports if the column name is valid (part of the table columns).
@ -248,6 +284,16 @@ func ByBiography(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldBiography, opts...).ToFunc()
}
// ByPublicKeyActor orders the results by the publicKeyActor field.
func ByPublicKeyActor(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldPublicKeyActor, opts...).ToFunc()
}
// ByPublicKeyAlgorithm orders the results by the publicKeyAlgorithm field.
func ByPublicKeyAlgorithm(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldPublicKeyAlgorithm, opts...).ToFunc()
}
// ByIndexable orders the results by the indexable field.
func ByIndexable(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldIndexable, opts...).ToFunc()
@ -324,6 +370,48 @@ func ByMentionedNotes(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
sqlgraph.OrderByNeighborTerms(s, newMentionedNotesStep(), append([]sql.OrderTerm{term}, terms...)...)
}
}
// ByServersCount orders the results by servers count.
func ByServersCount(opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborsCount(s, newServersStep(), opts...)
}
}
// ByServers orders the results by servers terms.
func ByServers(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newServersStep(), append([]sql.OrderTerm{term}, terms...)...)
}
}
// ByModeratedServersCount orders the results by moderatedServers count.
func ByModeratedServersCount(opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborsCount(s, newModeratedServersStep(), opts...)
}
}
// ByModeratedServers orders the results by moderatedServers terms.
func ByModeratedServers(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newModeratedServersStep(), append([]sql.OrderTerm{term}, terms...)...)
}
}
// ByAdministeredServersCount orders the results by administeredServers count.
func ByAdministeredServersCount(opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborsCount(s, newAdministeredServersStep(), opts...)
}
}
// ByAdministeredServers orders the results by administeredServers terms.
func ByAdministeredServers(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newAdministeredServersStep(), append([]sql.OrderTerm{term}, terms...)...)
}
}
func newAvatarImageStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
@ -352,3 +440,24 @@ func newMentionedNotesStep() *sqlgraph.Step {
sqlgraph.Edge(sqlgraph.M2M, true, MentionedNotesTable, MentionedNotesPrimaryKey...),
)
}
func newServersStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(ServersInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.M2M, true, ServersTable, ServersPrimaryKey...),
)
}
func newModeratedServersStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(ModeratedServersInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.M2M, true, ModeratedServersTable, ModeratedServersPrimaryKey...),
)
}
func newAdministeredServersStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(AdministeredServersInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.M2M, true, AdministeredServersTable, AdministeredServersPrimaryKey...),
)
}

View file

@ -3,7 +3,6 @@
package user
import (
"crypto/ed25519"
"time"
"entgo.io/ent/dialect/sql"
@ -98,15 +97,23 @@ func Biography(v string) predicate.User {
}
// PublicKey applies equality check predicate on the "publicKey" field. It's identical to PublicKeyEQ.
func PublicKey(v ed25519.PublicKey) predicate.User {
vc := []byte(v)
return predicate.User(sql.FieldEQ(FieldPublicKey, vc))
func PublicKey(v []byte) predicate.User {
return predicate.User(sql.FieldEQ(FieldPublicKey, v))
}
// PublicKeyActor applies equality check predicate on the "publicKeyActor" field. It's identical to PublicKeyActorEQ.
func PublicKeyActor(v string) predicate.User {
return predicate.User(sql.FieldEQ(FieldPublicKeyActor, v))
}
// PublicKeyAlgorithm applies equality check predicate on the "publicKeyAlgorithm" field. It's identical to PublicKeyAlgorithmEQ.
func PublicKeyAlgorithm(v string) predicate.User {
return predicate.User(sql.FieldEQ(FieldPublicKeyAlgorithm, v))
}
// PrivateKey applies equality check predicate on the "privateKey" field. It's identical to PrivateKeyEQ.
func PrivateKey(v ed25519.PrivateKey) predicate.User {
vc := []byte(v)
return predicate.User(sql.FieldEQ(FieldPrivateKey, vc))
func PrivateKey(v []byte) predicate.User {
return predicate.User(sql.FieldEQ(FieldPrivateKey, v))
}
// Indexable applies equality check predicate on the "indexable" field. It's identical to IndexableEQ.
@ -560,111 +567,213 @@ func BiographyContainsFold(v string) predicate.User {
}
// PublicKeyEQ applies the EQ predicate on the "publicKey" field.
func PublicKeyEQ(v ed25519.PublicKey) predicate.User {
vc := []byte(v)
return predicate.User(sql.FieldEQ(FieldPublicKey, vc))
func PublicKeyEQ(v []byte) predicate.User {
return predicate.User(sql.FieldEQ(FieldPublicKey, v))
}
// PublicKeyNEQ applies the NEQ predicate on the "publicKey" field.
func PublicKeyNEQ(v ed25519.PublicKey) predicate.User {
vc := []byte(v)
return predicate.User(sql.FieldNEQ(FieldPublicKey, vc))
func PublicKeyNEQ(v []byte) predicate.User {
return predicate.User(sql.FieldNEQ(FieldPublicKey, v))
}
// PublicKeyIn applies the In predicate on the "publicKey" field.
func PublicKeyIn(vs ...ed25519.PublicKey) predicate.User {
v := make([]any, len(vs))
for i := range v {
v[i] = []byte(vs[i])
}
return predicate.User(sql.FieldIn(FieldPublicKey, v...))
func PublicKeyIn(vs ...[]byte) predicate.User {
return predicate.User(sql.FieldIn(FieldPublicKey, vs...))
}
// PublicKeyNotIn applies the NotIn predicate on the "publicKey" field.
func PublicKeyNotIn(vs ...ed25519.PublicKey) predicate.User {
v := make([]any, len(vs))
for i := range v {
v[i] = []byte(vs[i])
}
return predicate.User(sql.FieldNotIn(FieldPublicKey, v...))
func PublicKeyNotIn(vs ...[]byte) predicate.User {
return predicate.User(sql.FieldNotIn(FieldPublicKey, vs...))
}
// PublicKeyGT applies the GT predicate on the "publicKey" field.
func PublicKeyGT(v ed25519.PublicKey) predicate.User {
vc := []byte(v)
return predicate.User(sql.FieldGT(FieldPublicKey, vc))
func PublicKeyGT(v []byte) predicate.User {
return predicate.User(sql.FieldGT(FieldPublicKey, v))
}
// PublicKeyGTE applies the GTE predicate on the "publicKey" field.
func PublicKeyGTE(v ed25519.PublicKey) predicate.User {
vc := []byte(v)
return predicate.User(sql.FieldGTE(FieldPublicKey, vc))
func PublicKeyGTE(v []byte) predicate.User {
return predicate.User(sql.FieldGTE(FieldPublicKey, v))
}
// PublicKeyLT applies the LT predicate on the "publicKey" field.
func PublicKeyLT(v ed25519.PublicKey) predicate.User {
vc := []byte(v)
return predicate.User(sql.FieldLT(FieldPublicKey, vc))
func PublicKeyLT(v []byte) predicate.User {
return predicate.User(sql.FieldLT(FieldPublicKey, v))
}
// PublicKeyLTE applies the LTE predicate on the "publicKey" field.
func PublicKeyLTE(v ed25519.PublicKey) predicate.User {
vc := []byte(v)
return predicate.User(sql.FieldLTE(FieldPublicKey, vc))
func PublicKeyLTE(v []byte) predicate.User {
return predicate.User(sql.FieldLTE(FieldPublicKey, v))
}
// PublicKeyActorEQ applies the EQ predicate on the "publicKeyActor" field.
func PublicKeyActorEQ(v string) predicate.User {
return predicate.User(sql.FieldEQ(FieldPublicKeyActor, v))
}
// PublicKeyActorNEQ applies the NEQ predicate on the "publicKeyActor" field.
func PublicKeyActorNEQ(v string) predicate.User {
return predicate.User(sql.FieldNEQ(FieldPublicKeyActor, v))
}
// PublicKeyActorIn applies the In predicate on the "publicKeyActor" field.
func PublicKeyActorIn(vs ...string) predicate.User {
return predicate.User(sql.FieldIn(FieldPublicKeyActor, vs...))
}
// PublicKeyActorNotIn applies the NotIn predicate on the "publicKeyActor" field.
func PublicKeyActorNotIn(vs ...string) predicate.User {
return predicate.User(sql.FieldNotIn(FieldPublicKeyActor, vs...))
}
// PublicKeyActorGT applies the GT predicate on the "publicKeyActor" field.
func PublicKeyActorGT(v string) predicate.User {
return predicate.User(sql.FieldGT(FieldPublicKeyActor, v))
}
// PublicKeyActorGTE applies the GTE predicate on the "publicKeyActor" field.
func PublicKeyActorGTE(v string) predicate.User {
return predicate.User(sql.FieldGTE(FieldPublicKeyActor, v))
}
// PublicKeyActorLT applies the LT predicate on the "publicKeyActor" field.
func PublicKeyActorLT(v string) predicate.User {
return predicate.User(sql.FieldLT(FieldPublicKeyActor, v))
}
// PublicKeyActorLTE applies the LTE predicate on the "publicKeyActor" field.
func PublicKeyActorLTE(v string) predicate.User {
return predicate.User(sql.FieldLTE(FieldPublicKeyActor, v))
}
// PublicKeyActorContains applies the Contains predicate on the "publicKeyActor" field.
func PublicKeyActorContains(v string) predicate.User {
return predicate.User(sql.FieldContains(FieldPublicKeyActor, v))
}
// PublicKeyActorHasPrefix applies the HasPrefix predicate on the "publicKeyActor" field.
func PublicKeyActorHasPrefix(v string) predicate.User {
return predicate.User(sql.FieldHasPrefix(FieldPublicKeyActor, v))
}
// PublicKeyActorHasSuffix applies the HasSuffix predicate on the "publicKeyActor" field.
func PublicKeyActorHasSuffix(v string) predicate.User {
return predicate.User(sql.FieldHasSuffix(FieldPublicKeyActor, v))
}
// PublicKeyActorEqualFold applies the EqualFold predicate on the "publicKeyActor" field.
func PublicKeyActorEqualFold(v string) predicate.User {
return predicate.User(sql.FieldEqualFold(FieldPublicKeyActor, v))
}
// PublicKeyActorContainsFold applies the ContainsFold predicate on the "publicKeyActor" field.
func PublicKeyActorContainsFold(v string) predicate.User {
return predicate.User(sql.FieldContainsFold(FieldPublicKeyActor, v))
}
// PublicKeyAlgorithmEQ applies the EQ predicate on the "publicKeyAlgorithm" field.
func PublicKeyAlgorithmEQ(v string) predicate.User {
return predicate.User(sql.FieldEQ(FieldPublicKeyAlgorithm, v))
}
// PublicKeyAlgorithmNEQ applies the NEQ predicate on the "publicKeyAlgorithm" field.
func PublicKeyAlgorithmNEQ(v string) predicate.User {
return predicate.User(sql.FieldNEQ(FieldPublicKeyAlgorithm, v))
}
// PublicKeyAlgorithmIn applies the In predicate on the "publicKeyAlgorithm" field.
func PublicKeyAlgorithmIn(vs ...string) predicate.User {
return predicate.User(sql.FieldIn(FieldPublicKeyAlgorithm, vs...))
}
// PublicKeyAlgorithmNotIn applies the NotIn predicate on the "publicKeyAlgorithm" field.
func PublicKeyAlgorithmNotIn(vs ...string) predicate.User {
return predicate.User(sql.FieldNotIn(FieldPublicKeyAlgorithm, vs...))
}
// PublicKeyAlgorithmGT applies the GT predicate on the "publicKeyAlgorithm" field.
func PublicKeyAlgorithmGT(v string) predicate.User {
return predicate.User(sql.FieldGT(FieldPublicKeyAlgorithm, v))
}
// PublicKeyAlgorithmGTE applies the GTE predicate on the "publicKeyAlgorithm" field.
func PublicKeyAlgorithmGTE(v string) predicate.User {
return predicate.User(sql.FieldGTE(FieldPublicKeyAlgorithm, v))
}
// PublicKeyAlgorithmLT applies the LT predicate on the "publicKeyAlgorithm" field.
func PublicKeyAlgorithmLT(v string) predicate.User {
return predicate.User(sql.FieldLT(FieldPublicKeyAlgorithm, v))
}
// PublicKeyAlgorithmLTE applies the LTE predicate on the "publicKeyAlgorithm" field.
func PublicKeyAlgorithmLTE(v string) predicate.User {
return predicate.User(sql.FieldLTE(FieldPublicKeyAlgorithm, v))
}
// PublicKeyAlgorithmContains applies the Contains predicate on the "publicKeyAlgorithm" field.
func PublicKeyAlgorithmContains(v string) predicate.User {
return predicate.User(sql.FieldContains(FieldPublicKeyAlgorithm, v))
}
// PublicKeyAlgorithmHasPrefix applies the HasPrefix predicate on the "publicKeyAlgorithm" field.
func PublicKeyAlgorithmHasPrefix(v string) predicate.User {
return predicate.User(sql.FieldHasPrefix(FieldPublicKeyAlgorithm, v))
}
// PublicKeyAlgorithmHasSuffix applies the HasSuffix predicate on the "publicKeyAlgorithm" field.
func PublicKeyAlgorithmHasSuffix(v string) predicate.User {
return predicate.User(sql.FieldHasSuffix(FieldPublicKeyAlgorithm, v))
}
// PublicKeyAlgorithmEqualFold applies the EqualFold predicate on the "publicKeyAlgorithm" field.
func PublicKeyAlgorithmEqualFold(v string) predicate.User {
return predicate.User(sql.FieldEqualFold(FieldPublicKeyAlgorithm, v))
}
// PublicKeyAlgorithmContainsFold applies the ContainsFold predicate on the "publicKeyAlgorithm" field.
func PublicKeyAlgorithmContainsFold(v string) predicate.User {
return predicate.User(sql.FieldContainsFold(FieldPublicKeyAlgorithm, v))
}
// PrivateKeyEQ applies the EQ predicate on the "privateKey" field.
func PrivateKeyEQ(v ed25519.PrivateKey) predicate.User {
vc := []byte(v)
return predicate.User(sql.FieldEQ(FieldPrivateKey, vc))
func PrivateKeyEQ(v []byte) predicate.User {
return predicate.User(sql.FieldEQ(FieldPrivateKey, v))
}
// PrivateKeyNEQ applies the NEQ predicate on the "privateKey" field.
func PrivateKeyNEQ(v ed25519.PrivateKey) predicate.User {
vc := []byte(v)
return predicate.User(sql.FieldNEQ(FieldPrivateKey, vc))
func PrivateKeyNEQ(v []byte) predicate.User {
return predicate.User(sql.FieldNEQ(FieldPrivateKey, v))
}
// PrivateKeyIn applies the In predicate on the "privateKey" field.
func PrivateKeyIn(vs ...ed25519.PrivateKey) predicate.User {
v := make([]any, len(vs))
for i := range v {
v[i] = []byte(vs[i])
}
return predicate.User(sql.FieldIn(FieldPrivateKey, v...))
func PrivateKeyIn(vs ...[]byte) predicate.User {
return predicate.User(sql.FieldIn(FieldPrivateKey, vs...))
}
// PrivateKeyNotIn applies the NotIn predicate on the "privateKey" field.
func PrivateKeyNotIn(vs ...ed25519.PrivateKey) predicate.User {
v := make([]any, len(vs))
for i := range v {
v[i] = []byte(vs[i])
}
return predicate.User(sql.FieldNotIn(FieldPrivateKey, v...))
func PrivateKeyNotIn(vs ...[]byte) predicate.User {
return predicate.User(sql.FieldNotIn(FieldPrivateKey, vs...))
}
// PrivateKeyGT applies the GT predicate on the "privateKey" field.
func PrivateKeyGT(v ed25519.PrivateKey) predicate.User {
vc := []byte(v)
return predicate.User(sql.FieldGT(FieldPrivateKey, vc))
func PrivateKeyGT(v []byte) predicate.User {
return predicate.User(sql.FieldGT(FieldPrivateKey, v))
}
// PrivateKeyGTE applies the GTE predicate on the "privateKey" field.
func PrivateKeyGTE(v ed25519.PrivateKey) predicate.User {
vc := []byte(v)
return predicate.User(sql.FieldGTE(FieldPrivateKey, vc))
func PrivateKeyGTE(v []byte) predicate.User {
return predicate.User(sql.FieldGTE(FieldPrivateKey, v))
}
// PrivateKeyLT applies the LT predicate on the "privateKey" field.
func PrivateKeyLT(v ed25519.PrivateKey) predicate.User {
vc := []byte(v)
return predicate.User(sql.FieldLT(FieldPrivateKey, vc))
func PrivateKeyLT(v []byte) predicate.User {
return predicate.User(sql.FieldLT(FieldPrivateKey, v))
}
// PrivateKeyLTE applies the LTE predicate on the "privateKey" field.
func PrivateKeyLTE(v ed25519.PrivateKey) predicate.User {
vc := []byte(v)
return predicate.User(sql.FieldLTE(FieldPrivateKey, vc))
func PrivateKeyLTE(v []byte) predicate.User {
return predicate.User(sql.FieldLTE(FieldPrivateKey, v))
}
// PrivateKeyIsNil applies the IsNil predicate on the "privateKey" field.
@ -1124,6 +1233,75 @@ func HasMentionedNotesWith(preds ...predicate.Note) predicate.User {
})
}
// HasServers applies the HasEdge predicate on the "servers" edge.
func HasServers() predicate.User {
return predicate.User(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.M2M, true, ServersTable, ServersPrimaryKey...),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasServersWith applies the HasEdge predicate on the "servers" edge with a given conditions (other predicates).
func HasServersWith(preds ...predicate.InstanceMetadata) predicate.User {
return predicate.User(func(s *sql.Selector) {
step := newServersStep()
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
p(s)
}
})
})
}
// HasModeratedServers applies the HasEdge predicate on the "moderatedServers" edge.
func HasModeratedServers() predicate.User {
return predicate.User(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.M2M, true, ModeratedServersTable, ModeratedServersPrimaryKey...),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasModeratedServersWith applies the HasEdge predicate on the "moderatedServers" edge with a given conditions (other predicates).
func HasModeratedServersWith(preds ...predicate.InstanceMetadata) predicate.User {
return predicate.User(func(s *sql.Selector) {
step := newModeratedServersStep()
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
p(s)
}
})
})
}
// HasAdministeredServers applies the HasEdge predicate on the "administeredServers" edge.
func HasAdministeredServers() predicate.User {
return predicate.User(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.M2M, true, AdministeredServersTable, AdministeredServersPrimaryKey...),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasAdministeredServersWith applies the HasEdge predicate on the "administeredServers" edge with a given conditions (other predicates).
func HasAdministeredServersWith(preds ...predicate.InstanceMetadata) predicate.User {
return predicate.User(func(s *sql.Selector) {
step := newAdministeredServersStep()
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...))

View file

@ -4,7 +4,6 @@ package ent
import (
"context"
"crypto/ed25519"
"errors"
"fmt"
"time"
@ -15,6 +14,7 @@ import (
"entgo.io/ent/schema/field"
"github.com/google/uuid"
"github.com/lysand-org/versia-go/ent/image"
"github.com/lysand-org/versia-go/ent/instancemetadata"
"github.com/lysand-org/versia-go/ent/note"
"github.com/lysand-org/versia-go/ent/user"
"github.com/lysand-org/versia-go/pkg/lysand"
@ -115,14 +115,26 @@ func (uc *UserCreate) SetNillableBiography(s *string) *UserCreate {
}
// SetPublicKey sets the "publicKey" field.
func (uc *UserCreate) SetPublicKey(ek ed25519.PublicKey) *UserCreate {
uc.mutation.SetPublicKey(ek)
func (uc *UserCreate) SetPublicKey(b []byte) *UserCreate {
uc.mutation.SetPublicKey(b)
return uc
}
// SetPublicKeyActor sets the "publicKeyActor" field.
func (uc *UserCreate) SetPublicKeyActor(s string) *UserCreate {
uc.mutation.SetPublicKeyActor(s)
return uc
}
// SetPublicKeyAlgorithm sets the "publicKeyAlgorithm" field.
func (uc *UserCreate) SetPublicKeyAlgorithm(s string) *UserCreate {
uc.mutation.SetPublicKeyAlgorithm(s)
return uc
}
// SetPrivateKey sets the "privateKey" field.
func (uc *UserCreate) SetPrivateKey(ek ed25519.PrivateKey) *UserCreate {
uc.mutation.SetPrivateKey(ek)
func (uc *UserCreate) SetPrivateKey(b []byte) *UserCreate {
uc.mutation.SetPrivateKey(b)
return uc
}
@ -272,6 +284,51 @@ func (uc *UserCreate) AddMentionedNotes(n ...*Note) *UserCreate {
return uc.AddMentionedNoteIDs(ids...)
}
// AddServerIDs adds the "servers" edge to the InstanceMetadata entity by IDs.
func (uc *UserCreate) AddServerIDs(ids ...uuid.UUID) *UserCreate {
uc.mutation.AddServerIDs(ids...)
return uc
}
// AddServers adds the "servers" edges to the InstanceMetadata entity.
func (uc *UserCreate) AddServers(i ...*InstanceMetadata) *UserCreate {
ids := make([]uuid.UUID, len(i))
for j := range i {
ids[j] = i[j].ID
}
return uc.AddServerIDs(ids...)
}
// AddModeratedServerIDs adds the "moderatedServers" edge to the InstanceMetadata entity by IDs.
func (uc *UserCreate) AddModeratedServerIDs(ids ...uuid.UUID) *UserCreate {
uc.mutation.AddModeratedServerIDs(ids...)
return uc
}
// AddModeratedServers adds the "moderatedServers" edges to the InstanceMetadata entity.
func (uc *UserCreate) AddModeratedServers(i ...*InstanceMetadata) *UserCreate {
ids := make([]uuid.UUID, len(i))
for j := range i {
ids[j] = i[j].ID
}
return uc.AddModeratedServerIDs(ids...)
}
// AddAdministeredServerIDs adds the "administeredServers" edge to the InstanceMetadata entity by IDs.
func (uc *UserCreate) AddAdministeredServerIDs(ids ...uuid.UUID) *UserCreate {
uc.mutation.AddAdministeredServerIDs(ids...)
return uc
}
// AddAdministeredServers adds the "administeredServers" edges to the InstanceMetadata entity.
func (uc *UserCreate) AddAdministeredServers(i ...*InstanceMetadata) *UserCreate {
ids := make([]uuid.UUID, len(i))
for j := range i {
ids[j] = i[j].ID
}
return uc.AddAdministeredServerIDs(ids...)
}
// Mutation returns the UserMutation object of the builder.
func (uc *UserCreate) Mutation() *UserMutation {
return uc.mutation
@ -375,6 +432,12 @@ func (uc *UserCreate) check() error {
if _, ok := uc.mutation.PublicKey(); !ok {
return &ValidationError{Name: "publicKey", err: errors.New(`ent: missing required field "User.publicKey"`)}
}
if _, ok := uc.mutation.PublicKeyActor(); !ok {
return &ValidationError{Name: "publicKeyActor", err: errors.New(`ent: missing required field "User.publicKeyActor"`)}
}
if _, ok := uc.mutation.PublicKeyAlgorithm(); !ok {
return &ValidationError{Name: "publicKeyAlgorithm", err: errors.New(`ent: missing required field "User.publicKeyAlgorithm"`)}
}
if _, ok := uc.mutation.Indexable(); !ok {
return &ValidationError{Name: "indexable", err: errors.New(`ent: missing required field "User.indexable"`)}
}
@ -505,6 +568,14 @@ func (uc *UserCreate) createSpec() (*User, *sqlgraph.CreateSpec) {
_spec.SetField(user.FieldPublicKey, field.TypeBytes, value)
_node.PublicKey = value
}
if value, ok := uc.mutation.PublicKeyActor(); ok {
_spec.SetField(user.FieldPublicKeyActor, field.TypeString, value)
_node.PublicKeyActor = value
}
if value, ok := uc.mutation.PublicKeyAlgorithm(); ok {
_spec.SetField(user.FieldPublicKeyAlgorithm, field.TypeString, value)
_node.PublicKeyAlgorithm = value
}
if value, ok := uc.mutation.PrivateKey(); ok {
_spec.SetField(user.FieldPrivateKey, field.TypeBytes, value)
_node.PrivateKey = value
@ -607,6 +678,54 @@ func (uc *UserCreate) createSpec() (*User, *sqlgraph.CreateSpec) {
}
_spec.Edges = append(_spec.Edges, edge)
}
if nodes := uc.mutation.ServersIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2M,
Inverse: true,
Table: user.ServersTable,
Columns: user.ServersPrimaryKey,
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(instancemetadata.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges = append(_spec.Edges, edge)
}
if nodes := uc.mutation.ModeratedServersIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2M,
Inverse: true,
Table: user.ModeratedServersTable,
Columns: user.ModeratedServersPrimaryKey,
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(instancemetadata.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges = append(_spec.Edges, edge)
}
if nodes := uc.mutation.AdministeredServersIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2M,
Inverse: true,
Table: user.AdministeredServersTable,
Columns: user.AdministeredServersPrimaryKey,
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(instancemetadata.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges = append(_spec.Edges, edge)
}
return _node, _spec
}
@ -774,7 +893,7 @@ func (u *UserUpsert) ClearBiography() *UserUpsert {
}
// SetPublicKey sets the "publicKey" field.
func (u *UserUpsert) SetPublicKey(v ed25519.PublicKey) *UserUpsert {
func (u *UserUpsert) SetPublicKey(v []byte) *UserUpsert {
u.Set(user.FieldPublicKey, v)
return u
}
@ -785,8 +904,32 @@ func (u *UserUpsert) UpdatePublicKey() *UserUpsert {
return u
}
// SetPublicKeyActor sets the "publicKeyActor" field.
func (u *UserUpsert) SetPublicKeyActor(v string) *UserUpsert {
u.Set(user.FieldPublicKeyActor, v)
return u
}
// UpdatePublicKeyActor sets the "publicKeyActor" field to the value that was provided on create.
func (u *UserUpsert) UpdatePublicKeyActor() *UserUpsert {
u.SetExcluded(user.FieldPublicKeyActor)
return u
}
// SetPublicKeyAlgorithm sets the "publicKeyAlgorithm" field.
func (u *UserUpsert) SetPublicKeyAlgorithm(v string) *UserUpsert {
u.Set(user.FieldPublicKeyAlgorithm, v)
return u
}
// UpdatePublicKeyAlgorithm sets the "publicKeyAlgorithm" field to the value that was provided on create.
func (u *UserUpsert) UpdatePublicKeyAlgorithm() *UserUpsert {
u.SetExcluded(user.FieldPublicKeyAlgorithm)
return u
}
// SetPrivateKey sets the "privateKey" field.
func (u *UserUpsert) SetPrivateKey(v ed25519.PrivateKey) *UserUpsert {
func (u *UserUpsert) SetPrivateKey(v []byte) *UserUpsert {
u.Set(user.FieldPrivateKey, v)
return u
}
@ -1084,7 +1227,7 @@ func (u *UserUpsertOne) ClearBiography() *UserUpsertOne {
}
// SetPublicKey sets the "publicKey" field.
func (u *UserUpsertOne) SetPublicKey(v ed25519.PublicKey) *UserUpsertOne {
func (u *UserUpsertOne) SetPublicKey(v []byte) *UserUpsertOne {
return u.Update(func(s *UserUpsert) {
s.SetPublicKey(v)
})
@ -1097,8 +1240,36 @@ func (u *UserUpsertOne) UpdatePublicKey() *UserUpsertOne {
})
}
// SetPublicKeyActor sets the "publicKeyActor" field.
func (u *UserUpsertOne) SetPublicKeyActor(v string) *UserUpsertOne {
return u.Update(func(s *UserUpsert) {
s.SetPublicKeyActor(v)
})
}
// UpdatePublicKeyActor sets the "publicKeyActor" field to the value that was provided on create.
func (u *UserUpsertOne) UpdatePublicKeyActor() *UserUpsertOne {
return u.Update(func(s *UserUpsert) {
s.UpdatePublicKeyActor()
})
}
// SetPublicKeyAlgorithm sets the "publicKeyAlgorithm" field.
func (u *UserUpsertOne) SetPublicKeyAlgorithm(v string) *UserUpsertOne {
return u.Update(func(s *UserUpsert) {
s.SetPublicKeyAlgorithm(v)
})
}
// UpdatePublicKeyAlgorithm sets the "publicKeyAlgorithm" field to the value that was provided on create.
func (u *UserUpsertOne) UpdatePublicKeyAlgorithm() *UserUpsertOne {
return u.Update(func(s *UserUpsert) {
s.UpdatePublicKeyAlgorithm()
})
}
// SetPrivateKey sets the "privateKey" field.
func (u *UserUpsertOne) SetPrivateKey(v ed25519.PrivateKey) *UserUpsertOne {
func (u *UserUpsertOne) SetPrivateKey(v []byte) *UserUpsertOne {
return u.Update(func(s *UserUpsert) {
s.SetPrivateKey(v)
})
@ -1582,7 +1753,7 @@ func (u *UserUpsertBulk) ClearBiography() *UserUpsertBulk {
}
// SetPublicKey sets the "publicKey" field.
func (u *UserUpsertBulk) SetPublicKey(v ed25519.PublicKey) *UserUpsertBulk {
func (u *UserUpsertBulk) SetPublicKey(v []byte) *UserUpsertBulk {
return u.Update(func(s *UserUpsert) {
s.SetPublicKey(v)
})
@ -1595,8 +1766,36 @@ func (u *UserUpsertBulk) UpdatePublicKey() *UserUpsertBulk {
})
}
// SetPublicKeyActor sets the "publicKeyActor" field.
func (u *UserUpsertBulk) SetPublicKeyActor(v string) *UserUpsertBulk {
return u.Update(func(s *UserUpsert) {
s.SetPublicKeyActor(v)
})
}
// UpdatePublicKeyActor sets the "publicKeyActor" field to the value that was provided on create.
func (u *UserUpsertBulk) UpdatePublicKeyActor() *UserUpsertBulk {
return u.Update(func(s *UserUpsert) {
s.UpdatePublicKeyActor()
})
}
// SetPublicKeyAlgorithm sets the "publicKeyAlgorithm" field.
func (u *UserUpsertBulk) SetPublicKeyAlgorithm(v string) *UserUpsertBulk {
return u.Update(func(s *UserUpsert) {
s.SetPublicKeyAlgorithm(v)
})
}
// UpdatePublicKeyAlgorithm sets the "publicKeyAlgorithm" field to the value that was provided on create.
func (u *UserUpsertBulk) UpdatePublicKeyAlgorithm() *UserUpsertBulk {
return u.Update(func(s *UserUpsert) {
s.UpdatePublicKeyAlgorithm()
})
}
// SetPrivateKey sets the "privateKey" field.
func (u *UserUpsertBulk) SetPrivateKey(v ed25519.PrivateKey) *UserUpsertBulk {
func (u *UserUpsertBulk) SetPrivateKey(v []byte) *UserUpsertBulk {
return u.Update(func(s *UserUpsert) {
s.SetPrivateKey(v)
})

View file

@ -13,6 +13,7 @@ import (
"entgo.io/ent/schema/field"
"github.com/google/uuid"
"github.com/lysand-org/versia-go/ent/image"
"github.com/lysand-org/versia-go/ent/instancemetadata"
"github.com/lysand-org/versia-go/ent/note"
"github.com/lysand-org/versia-go/ent/predicate"
"github.com/lysand-org/versia-go/ent/user"
@ -21,15 +22,18 @@ import (
// UserQuery is the builder for querying User entities.
type UserQuery struct {
config
ctx *QueryContext
order []user.OrderOption
inters []Interceptor
predicates []predicate.User
withAvatarImage *ImageQuery
withHeaderImage *ImageQuery
withAuthoredNotes *NoteQuery
withMentionedNotes *NoteQuery
withFKs bool
ctx *QueryContext
order []user.OrderOption
inters []Interceptor
predicates []predicate.User
withAvatarImage *ImageQuery
withHeaderImage *ImageQuery
withAuthoredNotes *NoteQuery
withMentionedNotes *NoteQuery
withServers *InstanceMetadataQuery
withModeratedServers *InstanceMetadataQuery
withAdministeredServers *InstanceMetadataQuery
withFKs bool
// intermediate query (i.e. traversal path).
sql *sql.Selector
path func(context.Context) (*sql.Selector, error)
@ -154,6 +158,72 @@ func (uq *UserQuery) QueryMentionedNotes() *NoteQuery {
return query
}
// QueryServers chains the current query on the "servers" edge.
func (uq *UserQuery) QueryServers() *InstanceMetadataQuery {
query := (&InstanceMetadataClient{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(instancemetadata.Table, instancemetadata.FieldID),
sqlgraph.Edge(sqlgraph.M2M, true, user.ServersTable, user.ServersPrimaryKey...),
)
fromU = sqlgraph.SetNeighbors(uq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// QueryModeratedServers chains the current query on the "moderatedServers" edge.
func (uq *UserQuery) QueryModeratedServers() *InstanceMetadataQuery {
query := (&InstanceMetadataClient{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(instancemetadata.Table, instancemetadata.FieldID),
sqlgraph.Edge(sqlgraph.M2M, true, user.ModeratedServersTable, user.ModeratedServersPrimaryKey...),
)
fromU = sqlgraph.SetNeighbors(uq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// QueryAdministeredServers chains the current query on the "administeredServers" edge.
func (uq *UserQuery) QueryAdministeredServers() *InstanceMetadataQuery {
query := (&InstanceMetadataClient{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(instancemetadata.Table, instancemetadata.FieldID),
sqlgraph.Edge(sqlgraph.M2M, true, user.AdministeredServersTable, user.AdministeredServersPrimaryKey...),
)
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) {
@ -341,15 +411,18 @@ func (uq *UserQuery) Clone() *UserQuery {
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...),
withAvatarImage: uq.withAvatarImage.Clone(),
withHeaderImage: uq.withHeaderImage.Clone(),
withAuthoredNotes: uq.withAuthoredNotes.Clone(),
withMentionedNotes: uq.withMentionedNotes.Clone(),
config: uq.config,
ctx: uq.ctx.Clone(),
order: append([]user.OrderOption{}, uq.order...),
inters: append([]Interceptor{}, uq.inters...),
predicates: append([]predicate.User{}, uq.predicates...),
withAvatarImage: uq.withAvatarImage.Clone(),
withHeaderImage: uq.withHeaderImage.Clone(),
withAuthoredNotes: uq.withAuthoredNotes.Clone(),
withMentionedNotes: uq.withMentionedNotes.Clone(),
withServers: uq.withServers.Clone(),
withModeratedServers: uq.withModeratedServers.Clone(),
withAdministeredServers: uq.withAdministeredServers.Clone(),
// clone intermediate query.
sql: uq.sql.Clone(),
path: uq.path,
@ -400,6 +473,39 @@ func (uq *UserQuery) WithMentionedNotes(opts ...func(*NoteQuery)) *UserQuery {
return uq
}
// WithServers tells the query-builder to eager-load the nodes that are connected to
// the "servers" edge. The optional arguments are used to configure the query builder of the edge.
func (uq *UserQuery) WithServers(opts ...func(*InstanceMetadataQuery)) *UserQuery {
query := (&InstanceMetadataClient{config: uq.config}).Query()
for _, opt := range opts {
opt(query)
}
uq.withServers = query
return uq
}
// WithModeratedServers tells the query-builder to eager-load the nodes that are connected to
// the "moderatedServers" edge. The optional arguments are used to configure the query builder of the edge.
func (uq *UserQuery) WithModeratedServers(opts ...func(*InstanceMetadataQuery)) *UserQuery {
query := (&InstanceMetadataClient{config: uq.config}).Query()
for _, opt := range opts {
opt(query)
}
uq.withModeratedServers = query
return uq
}
// WithAdministeredServers tells the query-builder to eager-load the nodes that are connected to
// the "administeredServers" edge. The optional arguments are used to configure the query builder of the edge.
func (uq *UserQuery) WithAdministeredServers(opts ...func(*InstanceMetadataQuery)) *UserQuery {
query := (&InstanceMetadataClient{config: uq.config}).Query()
for _, opt := range opts {
opt(query)
}
uq.withAdministeredServers = 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.
//
@ -479,11 +585,14 @@ func (uq *UserQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*User, e
nodes = []*User{}
withFKs = uq.withFKs
_spec = uq.querySpec()
loadedTypes = [4]bool{
loadedTypes = [7]bool{
uq.withAvatarImage != nil,
uq.withHeaderImage != nil,
uq.withAuthoredNotes != nil,
uq.withMentionedNotes != nil,
uq.withServers != nil,
uq.withModeratedServers != nil,
uq.withAdministeredServers != nil,
}
)
if uq.withAvatarImage != nil || uq.withHeaderImage != nil {
@ -536,6 +645,29 @@ func (uq *UserQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*User, e
return nil, err
}
}
if query := uq.withServers; query != nil {
if err := uq.loadServers(ctx, query, nodes,
func(n *User) { n.Edges.Servers = []*InstanceMetadata{} },
func(n *User, e *InstanceMetadata) { n.Edges.Servers = append(n.Edges.Servers, e) }); err != nil {
return nil, err
}
}
if query := uq.withModeratedServers; query != nil {
if err := uq.loadModeratedServers(ctx, query, nodes,
func(n *User) { n.Edges.ModeratedServers = []*InstanceMetadata{} },
func(n *User, e *InstanceMetadata) { n.Edges.ModeratedServers = append(n.Edges.ModeratedServers, e) }); err != nil {
return nil, err
}
}
if query := uq.withAdministeredServers; query != nil {
if err := uq.loadAdministeredServers(ctx, query, nodes,
func(n *User) { n.Edges.AdministeredServers = []*InstanceMetadata{} },
func(n *User, e *InstanceMetadata) {
n.Edges.AdministeredServers = append(n.Edges.AdministeredServers, e)
}); err != nil {
return nil, err
}
}
return nodes, nil
}
@ -695,6 +827,189 @@ func (uq *UserQuery) loadMentionedNotes(ctx context.Context, query *NoteQuery, n
}
return nil
}
func (uq *UserQuery) loadServers(ctx context.Context, query *InstanceMetadataQuery, nodes []*User, init func(*User), assign func(*User, *InstanceMetadata)) error {
edgeIDs := make([]driver.Value, len(nodes))
byID := make(map[uuid.UUID]*User)
nids := make(map[uuid.UUID]map[*User]struct{})
for i, node := range nodes {
edgeIDs[i] = node.ID
byID[node.ID] = node
if init != nil {
init(node)
}
}
query.Where(func(s *sql.Selector) {
joinT := sql.Table(user.ServersTable)
s.Join(joinT).On(s.C(instancemetadata.FieldID), joinT.C(user.ServersPrimaryKey[0]))
s.Where(sql.InValues(joinT.C(user.ServersPrimaryKey[1]), edgeIDs...))
columns := s.SelectedColumns()
s.Select(joinT.C(user.ServersPrimaryKey[1]))
s.AppendSelect(columns...)
s.SetDistinct(false)
})
if err := query.prepareQuery(ctx); err != nil {
return err
}
qr := QuerierFunc(func(ctx context.Context, q Query) (Value, error) {
return query.sqlAll(ctx, func(_ context.Context, spec *sqlgraph.QuerySpec) {
assign := spec.Assign
values := spec.ScanValues
spec.ScanValues = func(columns []string) ([]any, error) {
values, err := values(columns[1:])
if err != nil {
return nil, err
}
return append([]any{new(uuid.UUID)}, values...), nil
}
spec.Assign = func(columns []string, values []any) error {
outValue := *values[0].(*uuid.UUID)
inValue := *values[1].(*uuid.UUID)
if nids[inValue] == nil {
nids[inValue] = map[*User]struct{}{byID[outValue]: {}}
return assign(columns[1:], values[1:])
}
nids[inValue][byID[outValue]] = struct{}{}
return nil
}
})
})
neighbors, err := withInterceptors[[]*InstanceMetadata](ctx, query, qr, query.inters)
if err != nil {
return err
}
for _, n := range neighbors {
nodes, ok := nids[n.ID]
if !ok {
return fmt.Errorf(`unexpected "servers" node returned %v`, n.ID)
}
for kn := range nodes {
assign(kn, n)
}
}
return nil
}
func (uq *UserQuery) loadModeratedServers(ctx context.Context, query *InstanceMetadataQuery, nodes []*User, init func(*User), assign func(*User, *InstanceMetadata)) error {
edgeIDs := make([]driver.Value, len(nodes))
byID := make(map[uuid.UUID]*User)
nids := make(map[uuid.UUID]map[*User]struct{})
for i, node := range nodes {
edgeIDs[i] = node.ID
byID[node.ID] = node
if init != nil {
init(node)
}
}
query.Where(func(s *sql.Selector) {
joinT := sql.Table(user.ModeratedServersTable)
s.Join(joinT).On(s.C(instancemetadata.FieldID), joinT.C(user.ModeratedServersPrimaryKey[0]))
s.Where(sql.InValues(joinT.C(user.ModeratedServersPrimaryKey[1]), edgeIDs...))
columns := s.SelectedColumns()
s.Select(joinT.C(user.ModeratedServersPrimaryKey[1]))
s.AppendSelect(columns...)
s.SetDistinct(false)
})
if err := query.prepareQuery(ctx); err != nil {
return err
}
qr := QuerierFunc(func(ctx context.Context, q Query) (Value, error) {
return query.sqlAll(ctx, func(_ context.Context, spec *sqlgraph.QuerySpec) {
assign := spec.Assign
values := spec.ScanValues
spec.ScanValues = func(columns []string) ([]any, error) {
values, err := values(columns[1:])
if err != nil {
return nil, err
}
return append([]any{new(uuid.UUID)}, values...), nil
}
spec.Assign = func(columns []string, values []any) error {
outValue := *values[0].(*uuid.UUID)
inValue := *values[1].(*uuid.UUID)
if nids[inValue] == nil {
nids[inValue] = map[*User]struct{}{byID[outValue]: {}}
return assign(columns[1:], values[1:])
}
nids[inValue][byID[outValue]] = struct{}{}
return nil
}
})
})
neighbors, err := withInterceptors[[]*InstanceMetadata](ctx, query, qr, query.inters)
if err != nil {
return err
}
for _, n := range neighbors {
nodes, ok := nids[n.ID]
if !ok {
return fmt.Errorf(`unexpected "moderatedServers" node returned %v`, n.ID)
}
for kn := range nodes {
assign(kn, n)
}
}
return nil
}
func (uq *UserQuery) loadAdministeredServers(ctx context.Context, query *InstanceMetadataQuery, nodes []*User, init func(*User), assign func(*User, *InstanceMetadata)) error {
edgeIDs := make([]driver.Value, len(nodes))
byID := make(map[uuid.UUID]*User)
nids := make(map[uuid.UUID]map[*User]struct{})
for i, node := range nodes {
edgeIDs[i] = node.ID
byID[node.ID] = node
if init != nil {
init(node)
}
}
query.Where(func(s *sql.Selector) {
joinT := sql.Table(user.AdministeredServersTable)
s.Join(joinT).On(s.C(instancemetadata.FieldID), joinT.C(user.AdministeredServersPrimaryKey[0]))
s.Where(sql.InValues(joinT.C(user.AdministeredServersPrimaryKey[1]), edgeIDs...))
columns := s.SelectedColumns()
s.Select(joinT.C(user.AdministeredServersPrimaryKey[1]))
s.AppendSelect(columns...)
s.SetDistinct(false)
})
if err := query.prepareQuery(ctx); err != nil {
return err
}
qr := QuerierFunc(func(ctx context.Context, q Query) (Value, error) {
return query.sqlAll(ctx, func(_ context.Context, spec *sqlgraph.QuerySpec) {
assign := spec.Assign
values := spec.ScanValues
spec.ScanValues = func(columns []string) ([]any, error) {
values, err := values(columns[1:])
if err != nil {
return nil, err
}
return append([]any{new(uuid.UUID)}, values...), nil
}
spec.Assign = func(columns []string, values []any) error {
outValue := *values[0].(*uuid.UUID)
inValue := *values[1].(*uuid.UUID)
if nids[inValue] == nil {
nids[inValue] = map[*User]struct{}{byID[outValue]: {}}
return assign(columns[1:], values[1:])
}
nids[inValue][byID[outValue]] = struct{}{}
return nil
}
})
})
neighbors, err := withInterceptors[[]*InstanceMetadata](ctx, query, qr, query.inters)
if err != nil {
return err
}
for _, n := range neighbors {
nodes, ok := nids[n.ID]
if !ok {
return fmt.Errorf(`unexpected "administeredServers" node returned %v`, n.ID)
}
for kn := range nodes {
assign(kn, n)
}
}
return nil
}
func (uq *UserQuery) sqlCount(ctx context.Context) (int, error) {
_spec := uq.querySpec()

View file

@ -4,7 +4,6 @@ package ent
import (
"context"
"crypto/ed25519"
"errors"
"fmt"
"time"
@ -15,6 +14,7 @@ import (
"entgo.io/ent/schema/field"
"github.com/google/uuid"
"github.com/lysand-org/versia-go/ent/image"
"github.com/lysand-org/versia-go/ent/instancemetadata"
"github.com/lysand-org/versia-go/ent/note"
"github.com/lysand-org/versia-go/ent/predicate"
"github.com/lysand-org/versia-go/ent/user"
@ -141,14 +141,42 @@ func (uu *UserUpdate) ClearBiography() *UserUpdate {
}
// SetPublicKey sets the "publicKey" field.
func (uu *UserUpdate) SetPublicKey(ek ed25519.PublicKey) *UserUpdate {
uu.mutation.SetPublicKey(ek)
func (uu *UserUpdate) SetPublicKey(b []byte) *UserUpdate {
uu.mutation.SetPublicKey(b)
return uu
}
// SetPublicKeyActor sets the "publicKeyActor" field.
func (uu *UserUpdate) SetPublicKeyActor(s string) *UserUpdate {
uu.mutation.SetPublicKeyActor(s)
return uu
}
// SetNillablePublicKeyActor sets the "publicKeyActor" field if the given value is not nil.
func (uu *UserUpdate) SetNillablePublicKeyActor(s *string) *UserUpdate {
if s != nil {
uu.SetPublicKeyActor(*s)
}
return uu
}
// SetPublicKeyAlgorithm sets the "publicKeyAlgorithm" field.
func (uu *UserUpdate) SetPublicKeyAlgorithm(s string) *UserUpdate {
uu.mutation.SetPublicKeyAlgorithm(s)
return uu
}
// SetNillablePublicKeyAlgorithm sets the "publicKeyAlgorithm" field if the given value is not nil.
func (uu *UserUpdate) SetNillablePublicKeyAlgorithm(s *string) *UserUpdate {
if s != nil {
uu.SetPublicKeyAlgorithm(*s)
}
return uu
}
// SetPrivateKey sets the "privateKey" field.
func (uu *UserUpdate) SetPrivateKey(ek ed25519.PrivateKey) *UserUpdate {
uu.mutation.SetPrivateKey(ek)
func (uu *UserUpdate) SetPrivateKey(b []byte) *UserUpdate {
uu.mutation.SetPrivateKey(b)
return uu
}
@ -336,6 +364,51 @@ func (uu *UserUpdate) AddMentionedNotes(n ...*Note) *UserUpdate {
return uu.AddMentionedNoteIDs(ids...)
}
// AddServerIDs adds the "servers" edge to the InstanceMetadata entity by IDs.
func (uu *UserUpdate) AddServerIDs(ids ...uuid.UUID) *UserUpdate {
uu.mutation.AddServerIDs(ids...)
return uu
}
// AddServers adds the "servers" edges to the InstanceMetadata entity.
func (uu *UserUpdate) AddServers(i ...*InstanceMetadata) *UserUpdate {
ids := make([]uuid.UUID, len(i))
for j := range i {
ids[j] = i[j].ID
}
return uu.AddServerIDs(ids...)
}
// AddModeratedServerIDs adds the "moderatedServers" edge to the InstanceMetadata entity by IDs.
func (uu *UserUpdate) AddModeratedServerIDs(ids ...uuid.UUID) *UserUpdate {
uu.mutation.AddModeratedServerIDs(ids...)
return uu
}
// AddModeratedServers adds the "moderatedServers" edges to the InstanceMetadata entity.
func (uu *UserUpdate) AddModeratedServers(i ...*InstanceMetadata) *UserUpdate {
ids := make([]uuid.UUID, len(i))
for j := range i {
ids[j] = i[j].ID
}
return uu.AddModeratedServerIDs(ids...)
}
// AddAdministeredServerIDs adds the "administeredServers" edge to the InstanceMetadata entity by IDs.
func (uu *UserUpdate) AddAdministeredServerIDs(ids ...uuid.UUID) *UserUpdate {
uu.mutation.AddAdministeredServerIDs(ids...)
return uu
}
// AddAdministeredServers adds the "administeredServers" edges to the InstanceMetadata entity.
func (uu *UserUpdate) AddAdministeredServers(i ...*InstanceMetadata) *UserUpdate {
ids := make([]uuid.UUID, len(i))
for j := range i {
ids[j] = i[j].ID
}
return uu.AddAdministeredServerIDs(ids...)
}
// Mutation returns the UserMutation object of the builder.
func (uu *UserUpdate) Mutation() *UserMutation {
return uu.mutation
@ -395,6 +468,69 @@ func (uu *UserUpdate) RemoveMentionedNotes(n ...*Note) *UserUpdate {
return uu.RemoveMentionedNoteIDs(ids...)
}
// ClearServers clears all "servers" edges to the InstanceMetadata entity.
func (uu *UserUpdate) ClearServers() *UserUpdate {
uu.mutation.ClearServers()
return uu
}
// RemoveServerIDs removes the "servers" edge to InstanceMetadata entities by IDs.
func (uu *UserUpdate) RemoveServerIDs(ids ...uuid.UUID) *UserUpdate {
uu.mutation.RemoveServerIDs(ids...)
return uu
}
// RemoveServers removes "servers" edges to InstanceMetadata entities.
func (uu *UserUpdate) RemoveServers(i ...*InstanceMetadata) *UserUpdate {
ids := make([]uuid.UUID, len(i))
for j := range i {
ids[j] = i[j].ID
}
return uu.RemoveServerIDs(ids...)
}
// ClearModeratedServers clears all "moderatedServers" edges to the InstanceMetadata entity.
func (uu *UserUpdate) ClearModeratedServers() *UserUpdate {
uu.mutation.ClearModeratedServers()
return uu
}
// RemoveModeratedServerIDs removes the "moderatedServers" edge to InstanceMetadata entities by IDs.
func (uu *UserUpdate) RemoveModeratedServerIDs(ids ...uuid.UUID) *UserUpdate {
uu.mutation.RemoveModeratedServerIDs(ids...)
return uu
}
// RemoveModeratedServers removes "moderatedServers" edges to InstanceMetadata entities.
func (uu *UserUpdate) RemoveModeratedServers(i ...*InstanceMetadata) *UserUpdate {
ids := make([]uuid.UUID, len(i))
for j := range i {
ids[j] = i[j].ID
}
return uu.RemoveModeratedServerIDs(ids...)
}
// ClearAdministeredServers clears all "administeredServers" edges to the InstanceMetadata entity.
func (uu *UserUpdate) ClearAdministeredServers() *UserUpdate {
uu.mutation.ClearAdministeredServers()
return uu
}
// RemoveAdministeredServerIDs removes the "administeredServers" edge to InstanceMetadata entities by IDs.
func (uu *UserUpdate) RemoveAdministeredServerIDs(ids ...uuid.UUID) *UserUpdate {
uu.mutation.RemoveAdministeredServerIDs(ids...)
return uu
}
// RemoveAdministeredServers removes "administeredServers" edges to InstanceMetadata entities.
func (uu *UserUpdate) RemoveAdministeredServers(i ...*InstanceMetadata) *UserUpdate {
ids := make([]uuid.UUID, len(i))
for j := range i {
ids[j] = i[j].ID
}
return uu.RemoveAdministeredServerIDs(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) {
uu.defaults()
@ -529,6 +665,12 @@ func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) {
if value, ok := uu.mutation.PublicKey(); ok {
_spec.SetField(user.FieldPublicKey, field.TypeBytes, value)
}
if value, ok := uu.mutation.PublicKeyActor(); ok {
_spec.SetField(user.FieldPublicKeyActor, field.TypeString, value)
}
if value, ok := uu.mutation.PublicKeyAlgorithm(); ok {
_spec.SetField(user.FieldPublicKeyAlgorithm, field.TypeString, value)
}
if value, ok := uu.mutation.PrivateKey(); ok {
_spec.SetField(user.FieldPrivateKey, field.TypeBytes, value)
}
@ -712,6 +854,141 @@ func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) {
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if uu.mutation.ServersCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2M,
Inverse: true,
Table: user.ServersTable,
Columns: user.ServersPrimaryKey,
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(instancemetadata.FieldID, field.TypeUUID),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := uu.mutation.RemovedServersIDs(); len(nodes) > 0 && !uu.mutation.ServersCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2M,
Inverse: true,
Table: user.ServersTable,
Columns: user.ServersPrimaryKey,
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(instancemetadata.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := uu.mutation.ServersIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2M,
Inverse: true,
Table: user.ServersTable,
Columns: user.ServersPrimaryKey,
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(instancemetadata.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if uu.mutation.ModeratedServersCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2M,
Inverse: true,
Table: user.ModeratedServersTable,
Columns: user.ModeratedServersPrimaryKey,
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(instancemetadata.FieldID, field.TypeUUID),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := uu.mutation.RemovedModeratedServersIDs(); len(nodes) > 0 && !uu.mutation.ModeratedServersCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2M,
Inverse: true,
Table: user.ModeratedServersTable,
Columns: user.ModeratedServersPrimaryKey,
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(instancemetadata.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := uu.mutation.ModeratedServersIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2M,
Inverse: true,
Table: user.ModeratedServersTable,
Columns: user.ModeratedServersPrimaryKey,
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(instancemetadata.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if uu.mutation.AdministeredServersCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2M,
Inverse: true,
Table: user.AdministeredServersTable,
Columns: user.AdministeredServersPrimaryKey,
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(instancemetadata.FieldID, field.TypeUUID),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := uu.mutation.RemovedAdministeredServersIDs(); len(nodes) > 0 && !uu.mutation.AdministeredServersCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2M,
Inverse: true,
Table: user.AdministeredServersTable,
Columns: user.AdministeredServersPrimaryKey,
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(instancemetadata.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := uu.mutation.AdministeredServersIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2M,
Inverse: true,
Table: user.AdministeredServersTable,
Columns: user.AdministeredServersPrimaryKey,
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(instancemetadata.FieldID, field.TypeUUID),
},
}
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}
@ -839,14 +1116,42 @@ func (uuo *UserUpdateOne) ClearBiography() *UserUpdateOne {
}
// SetPublicKey sets the "publicKey" field.
func (uuo *UserUpdateOne) SetPublicKey(ek ed25519.PublicKey) *UserUpdateOne {
uuo.mutation.SetPublicKey(ek)
func (uuo *UserUpdateOne) SetPublicKey(b []byte) *UserUpdateOne {
uuo.mutation.SetPublicKey(b)
return uuo
}
// SetPublicKeyActor sets the "publicKeyActor" field.
func (uuo *UserUpdateOne) SetPublicKeyActor(s string) *UserUpdateOne {
uuo.mutation.SetPublicKeyActor(s)
return uuo
}
// SetNillablePublicKeyActor sets the "publicKeyActor" field if the given value is not nil.
func (uuo *UserUpdateOne) SetNillablePublicKeyActor(s *string) *UserUpdateOne {
if s != nil {
uuo.SetPublicKeyActor(*s)
}
return uuo
}
// SetPublicKeyAlgorithm sets the "publicKeyAlgorithm" field.
func (uuo *UserUpdateOne) SetPublicKeyAlgorithm(s string) *UserUpdateOne {
uuo.mutation.SetPublicKeyAlgorithm(s)
return uuo
}
// SetNillablePublicKeyAlgorithm sets the "publicKeyAlgorithm" field if the given value is not nil.
func (uuo *UserUpdateOne) SetNillablePublicKeyAlgorithm(s *string) *UserUpdateOne {
if s != nil {
uuo.SetPublicKeyAlgorithm(*s)
}
return uuo
}
// SetPrivateKey sets the "privateKey" field.
func (uuo *UserUpdateOne) SetPrivateKey(ek ed25519.PrivateKey) *UserUpdateOne {
uuo.mutation.SetPrivateKey(ek)
func (uuo *UserUpdateOne) SetPrivateKey(b []byte) *UserUpdateOne {
uuo.mutation.SetPrivateKey(b)
return uuo
}
@ -1034,6 +1339,51 @@ func (uuo *UserUpdateOne) AddMentionedNotes(n ...*Note) *UserUpdateOne {
return uuo.AddMentionedNoteIDs(ids...)
}
// AddServerIDs adds the "servers" edge to the InstanceMetadata entity by IDs.
func (uuo *UserUpdateOne) AddServerIDs(ids ...uuid.UUID) *UserUpdateOne {
uuo.mutation.AddServerIDs(ids...)
return uuo
}
// AddServers adds the "servers" edges to the InstanceMetadata entity.
func (uuo *UserUpdateOne) AddServers(i ...*InstanceMetadata) *UserUpdateOne {
ids := make([]uuid.UUID, len(i))
for j := range i {
ids[j] = i[j].ID
}
return uuo.AddServerIDs(ids...)
}
// AddModeratedServerIDs adds the "moderatedServers" edge to the InstanceMetadata entity by IDs.
func (uuo *UserUpdateOne) AddModeratedServerIDs(ids ...uuid.UUID) *UserUpdateOne {
uuo.mutation.AddModeratedServerIDs(ids...)
return uuo
}
// AddModeratedServers adds the "moderatedServers" edges to the InstanceMetadata entity.
func (uuo *UserUpdateOne) AddModeratedServers(i ...*InstanceMetadata) *UserUpdateOne {
ids := make([]uuid.UUID, len(i))
for j := range i {
ids[j] = i[j].ID
}
return uuo.AddModeratedServerIDs(ids...)
}
// AddAdministeredServerIDs adds the "administeredServers" edge to the InstanceMetadata entity by IDs.
func (uuo *UserUpdateOne) AddAdministeredServerIDs(ids ...uuid.UUID) *UserUpdateOne {
uuo.mutation.AddAdministeredServerIDs(ids...)
return uuo
}
// AddAdministeredServers adds the "administeredServers" edges to the InstanceMetadata entity.
func (uuo *UserUpdateOne) AddAdministeredServers(i ...*InstanceMetadata) *UserUpdateOne {
ids := make([]uuid.UUID, len(i))
for j := range i {
ids[j] = i[j].ID
}
return uuo.AddAdministeredServerIDs(ids...)
}
// Mutation returns the UserMutation object of the builder.
func (uuo *UserUpdateOne) Mutation() *UserMutation {
return uuo.mutation
@ -1093,6 +1443,69 @@ func (uuo *UserUpdateOne) RemoveMentionedNotes(n ...*Note) *UserUpdateOne {
return uuo.RemoveMentionedNoteIDs(ids...)
}
// ClearServers clears all "servers" edges to the InstanceMetadata entity.
func (uuo *UserUpdateOne) ClearServers() *UserUpdateOne {
uuo.mutation.ClearServers()
return uuo
}
// RemoveServerIDs removes the "servers" edge to InstanceMetadata entities by IDs.
func (uuo *UserUpdateOne) RemoveServerIDs(ids ...uuid.UUID) *UserUpdateOne {
uuo.mutation.RemoveServerIDs(ids...)
return uuo
}
// RemoveServers removes "servers" edges to InstanceMetadata entities.
func (uuo *UserUpdateOne) RemoveServers(i ...*InstanceMetadata) *UserUpdateOne {
ids := make([]uuid.UUID, len(i))
for j := range i {
ids[j] = i[j].ID
}
return uuo.RemoveServerIDs(ids...)
}
// ClearModeratedServers clears all "moderatedServers" edges to the InstanceMetadata entity.
func (uuo *UserUpdateOne) ClearModeratedServers() *UserUpdateOne {
uuo.mutation.ClearModeratedServers()
return uuo
}
// RemoveModeratedServerIDs removes the "moderatedServers" edge to InstanceMetadata entities by IDs.
func (uuo *UserUpdateOne) RemoveModeratedServerIDs(ids ...uuid.UUID) *UserUpdateOne {
uuo.mutation.RemoveModeratedServerIDs(ids...)
return uuo
}
// RemoveModeratedServers removes "moderatedServers" edges to InstanceMetadata entities.
func (uuo *UserUpdateOne) RemoveModeratedServers(i ...*InstanceMetadata) *UserUpdateOne {
ids := make([]uuid.UUID, len(i))
for j := range i {
ids[j] = i[j].ID
}
return uuo.RemoveModeratedServerIDs(ids...)
}
// ClearAdministeredServers clears all "administeredServers" edges to the InstanceMetadata entity.
func (uuo *UserUpdateOne) ClearAdministeredServers() *UserUpdateOne {
uuo.mutation.ClearAdministeredServers()
return uuo
}
// RemoveAdministeredServerIDs removes the "administeredServers" edge to InstanceMetadata entities by IDs.
func (uuo *UserUpdateOne) RemoveAdministeredServerIDs(ids ...uuid.UUID) *UserUpdateOne {
uuo.mutation.RemoveAdministeredServerIDs(ids...)
return uuo
}
// RemoveAdministeredServers removes "administeredServers" edges to InstanceMetadata entities.
func (uuo *UserUpdateOne) RemoveAdministeredServers(i ...*InstanceMetadata) *UserUpdateOne {
ids := make([]uuid.UUID, len(i))
for j := range i {
ids[j] = i[j].ID
}
return uuo.RemoveAdministeredServerIDs(ids...)
}
// Where appends a list predicates to the UserUpdate builder.
func (uuo *UserUpdateOne) Where(ps ...predicate.User) *UserUpdateOne {
uuo.mutation.Where(ps...)
@ -1257,6 +1670,12 @@ func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (_node *User, err error)
if value, ok := uuo.mutation.PublicKey(); ok {
_spec.SetField(user.FieldPublicKey, field.TypeBytes, value)
}
if value, ok := uuo.mutation.PublicKeyActor(); ok {
_spec.SetField(user.FieldPublicKeyActor, field.TypeString, value)
}
if value, ok := uuo.mutation.PublicKeyAlgorithm(); ok {
_spec.SetField(user.FieldPublicKeyAlgorithm, field.TypeString, value)
}
if value, ok := uuo.mutation.PrivateKey(); ok {
_spec.SetField(user.FieldPrivateKey, field.TypeBytes, value)
}
@ -1440,6 +1859,141 @@ func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (_node *User, err error)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if uuo.mutation.ServersCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2M,
Inverse: true,
Table: user.ServersTable,
Columns: user.ServersPrimaryKey,
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(instancemetadata.FieldID, field.TypeUUID),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := uuo.mutation.RemovedServersIDs(); len(nodes) > 0 && !uuo.mutation.ServersCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2M,
Inverse: true,
Table: user.ServersTable,
Columns: user.ServersPrimaryKey,
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(instancemetadata.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := uuo.mutation.ServersIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2M,
Inverse: true,
Table: user.ServersTable,
Columns: user.ServersPrimaryKey,
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(instancemetadata.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if uuo.mutation.ModeratedServersCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2M,
Inverse: true,
Table: user.ModeratedServersTable,
Columns: user.ModeratedServersPrimaryKey,
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(instancemetadata.FieldID, field.TypeUUID),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := uuo.mutation.RemovedModeratedServersIDs(); len(nodes) > 0 && !uuo.mutation.ModeratedServersCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2M,
Inverse: true,
Table: user.ModeratedServersTable,
Columns: user.ModeratedServersPrimaryKey,
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(instancemetadata.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := uuo.mutation.ModeratedServersIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2M,
Inverse: true,
Table: user.ModeratedServersTable,
Columns: user.ModeratedServersPrimaryKey,
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(instancemetadata.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if uuo.mutation.AdministeredServersCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2M,
Inverse: true,
Table: user.AdministeredServersTable,
Columns: user.AdministeredServersPrimaryKey,
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(instancemetadata.FieldID, field.TypeUUID),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := uuo.mutation.RemovedAdministeredServersIDs(); len(nodes) > 0 && !uuo.mutation.AdministeredServersCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2M,
Inverse: true,
Table: user.AdministeredServersTable,
Columns: user.AdministeredServersPrimaryKey,
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(instancemetadata.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := uuo.mutation.AdministeredServersIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2M,
Inverse: true,
Table: user.AdministeredServersTable,
Columns: user.AdministeredServersPrimaryKey,
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(instancemetadata.FieldID, field.TypeUUID),
},
}
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

View file

@ -6,6 +6,7 @@ var (
ErrUnauthorized = NewAPIError(401, "Unauthorized")
ErrForbidden = NewAPIError(403, "Forbidden")
ErrNotFound = NewAPIError(404, "Not found")
ErrUserNotFound = ErrNotFound(map[string]any{"reason": "user not found"})
ErrConflict = NewAPIError(409, "Conflict")
ErrUsernameTaken = NewAPIError(409, "Username is taken")
ErrRateLimitExceeded = NewAPIError(429, "Rate limit exceeded")

View file

@ -2,6 +2,7 @@ package api_schema
import (
"github.com/google/uuid"
"github.com/lysand-org/versia-go/pkg/lysand"
)
type User struct {
@ -9,9 +10,16 @@ type User struct {
Username string `json:"username"`
}
type LysandUser lysand.User
type FetchUserResponse = APIResponse[User]
type CreateUserRequest struct {
Username string `json:"username" validate:"required,username_regex,min=3,max=32"`
Username string `json:"username" validate:"required,username_regex,min=1,max=32"`
Password string `json:"password" validate:"required,min=8,max=256"`
}
type SearchUserRequest struct {
Username string `query:"username" validate:"required,username_regex,min=1,max=32"`
Domain *string `query:"domain" validate:"domain_regex"`
}

View file

@ -0,0 +1,96 @@
package entity
import (
"github.com/lysand-org/versia-go/ent"
"github.com/lysand-org/versia-go/pkg/lysand"
versiacrypto "github.com/lysand-org/versia-go/pkg/lysand/crypto"
)
type InstanceMetadata struct {
*ent.InstanceMetadata
Moderators []User
ModeratorsCollection *lysand.URL
Admins []User
AdminsCollection *lysand.URL
SharedInbox *lysand.URL
PublicKey *lysand.SPKIPublicKey
Logo *lysand.ImageContentTypeMap
Banner *lysand.ImageContentTypeMap
}
func NewInstanceMetadata(dbData *ent.InstanceMetadata) (*InstanceMetadata, error) {
n := &InstanceMetadata{
InstanceMetadata: dbData,
PublicKey: &lysand.SPKIPublicKey{},
}
var err error
if n.PublicKey.Key, err = versiacrypto.ToTypedKey(dbData.PublicKeyAlgorithm, dbData.PublicKey); err != nil {
return nil, err
}
if n.SharedInbox, err = lysand.ParseURL(dbData.SharedInboxURI); err != nil {
return nil, err
}
if dbData.ModeratorsURI != nil {
if n.ModeratorsCollection, err = lysand.ParseURL(*dbData.ModeratorsURI); err != nil {
return nil, err
}
}
if dbData.AdminsURI != nil {
if n.AdminsCollection, err = lysand.ParseURL(*dbData.AdminsURI); err != nil {
return nil, err
}
}
for _, r := range dbData.Edges.Moderators {
u, err := NewUser(r)
if err != nil {
return nil, err
}
n.Moderators = append(n.Moderators, *u)
}
for _, r := range dbData.Edges.Admins {
u, err := NewUser(r)
if err != nil {
return nil, err
}
n.Admins = append(n.Admins, *u)
}
return n, nil
}
func (m InstanceMetadata) ToLysand() lysand.InstanceMetadata {
return lysand.InstanceMetadata{
Extensions: m.Extensions,
Name: m.Name,
Description: m.Description,
Host: m.Host,
SharedInbox: m.SharedInbox,
Moderators: m.ModeratorsCollection,
Admins: m.AdminsCollection,
Logo: m.Logo,
Banner: m.Banner,
PublicKey: lysand.InstancePublicKey{
Algorithm: m.PublicKeyAlgorithm,
Key: m.PublicKey,
},
Software: lysand.InstanceSoftware{
Name: m.SoftwareName,
Version: m.SoftwareVersion,
},
Compatibility: lysand.InstanceCompatibility{
Versions: m.SupportedVersions,
Extensions: m.SupportedExtensions,
},
}
}

View file

@ -2,6 +2,7 @@ package entity
import (
"github.com/lysand-org/versia-go/internal/helpers"
versiacrypto "github.com/lysand-org/versia-go/pkg/lysand/crypto"
"net/url"
"github.com/lysand-org/versia-go/ent"
@ -12,12 +13,14 @@ import (
type User struct {
*ent.User
URI *lysand.URL
Inbox *lysand.URL
Outbox *lysand.URL
Featured *lysand.URL
Followers *lysand.URL
Following *lysand.URL
URI *lysand.URL
PKActorURI *lysand.URL
PublicKey *lysand.SPKIPublicKey
Inbox *lysand.URL
Outbox *lysand.URL
Featured *lysand.URL
Followers *lysand.URL
Following *lysand.URL
DisplayName string
LysandAvatar lysand.ImageContentTypeMap
@ -25,38 +28,52 @@ type User struct {
Signer lysand.Signer
}
func NewUser(dbUser *ent.User) (*User, error) {
u := &User{User: dbUser}
func NewUser(dbData *ent.User) (*User, error) {
u := &User{
User: dbData,
PublicKey: &lysand.SPKIPublicKey{
Key: nil,
Algorithm: dbData.PublicKeyAlgorithm,
},
DisplayName: dbData.Username,
u.DisplayName = u.Username
if dbUser.DisplayName != nil {
u.DisplayName = *dbUser.DisplayName
LysandAvatar: lysandAvatar(dbData),
LysandBiography: lysandBiography(dbData),
}
if dbData.DisplayName != nil {
u.DisplayName = *dbData.DisplayName
}
var err error
if u.URI, err = lysand.ParseURL(dbUser.URI); err != nil {
return nil, err
}
if u.Inbox, err = lysand.ParseURL(dbUser.Inbox); err != nil {
return nil, err
}
if u.Outbox, err = lysand.ParseURL(dbUser.Outbox); err != nil {
return nil, err
}
if u.Featured, err = lysand.ParseURL(dbUser.Featured); err != nil {
return nil, err
}
if u.Followers, err = lysand.ParseURL(dbUser.Followers); err != nil {
return nil, err
}
if u.Following, err = lysand.ParseURL(dbUser.Following); err != nil {
if u.PublicKey.Key, err = versiacrypto.ToTypedKey(dbData.PublicKeyAlgorithm, dbData.PublicKey); err != nil {
return nil, err
}
if u.URI, err = lysand.ParseURL(dbData.URI); err != nil {
return nil, err
}
if u.PKActorURI, err = lysand.ParseURL(dbData.PublicKeyActor); err != nil {
return nil, err
}
if u.Inbox, err = lysand.ParseURL(dbData.Inbox); err != nil {
return nil, err
}
if u.Outbox, err = lysand.ParseURL(dbData.Outbox); err != nil {
return nil, err
}
if u.Featured, err = lysand.ParseURL(dbData.Featured); err != nil {
return nil, err
}
if u.Followers, err = lysand.ParseURL(dbData.Followers); err != nil {
return nil, err
}
if u.Following, err = lysand.ParseURL(dbData.Following); err != nil {
return nil, err
}
u.LysandAvatar = lysandAvatar(dbUser)
u.LysandBiography = lysandBiography(dbUser)
u.Signer = lysand.Signer{
PrivateKey: dbUser.PrivateKey,
PrivateKey: dbData.PrivateKey,
UserURL: u.URI.ToStd(),
}
@ -76,9 +93,10 @@ func (u User) ToLysand() *lysand.User {
Avatar: u.LysandAvatar,
Header: imageMap(u.Edges.HeaderImage),
Indexable: u.Indexable,
PublicKey: lysand.PublicKey{
Actor: utils.UserAPIURL(u.ID),
PublicKey: lysand.SPKIPublicKey(u.PublicKey),
PublicKey: lysand.UserPublicKey{
Actor: u.PKActorURI,
Algorithm: u.PublicKeyAlgorithm,
Key: u.PublicKey,
},
Bio: u.LysandBiography,
Fields: u.Fields,
@ -88,10 +106,6 @@ func (u User) ToLysand() *lysand.User {
Featured: u.Featured,
Followers: u.Followers,
Following: u.Following,
// TODO: Remove these, they got deprecated and moved into an extension
Likes: utils.UserLikesAPIURL(u.ID),
Dislikes: utils.UserDislikesAPIURL(u.ID),
}
}

View file

@ -4,17 +4,22 @@ import (
"github.com/go-logr/logr"
"github.com/gofiber/fiber/v2"
"github.com/lysand-org/versia-go/config"
"github.com/lysand-org/versia-go/internal/service"
"github.com/lysand-org/versia-go/pkg/webfinger"
)
type Handler struct {
instanceMetadataService service.InstanceMetadataService
hostMeta webfinger.HostMeta
log logr.Logger
}
func New(log logr.Logger) *Handler {
func New(instanceMetadataService service.InstanceMetadataService, log logr.Logger) *Handler {
return &Handler{
instanceMetadataService: instanceMetadataService,
hostMeta: webfinger.NewHostMeta(config.C.PublicAddress),
log: log.WithName("users"),
@ -22,7 +27,11 @@ func New(log logr.Logger) *Handler {
}
func (i *Handler) Register(r fiber.Router) {
r.Get("/.well-known/lysand", i.GetLysandServerMetadata)
r.Get("/.well-known/versia", i.GetLysandInstanceMetadata)
r.Get("/.well-known/versia/admins", i.GetLysandInstanceMetadata)
r.Get("/.well-known/versia/moderators", i.GetLysandInstanceMetadata)
// Webfinger host meta spec
r.Get("/.well-known/host-meta", i.GetHostMeta)
r.Get("/.well-known/host-meta.json", i.GetHostMetaJSON)
}

View file

@ -0,0 +1,14 @@
package meta_handler
import (
"github.com/gofiber/fiber/v2"
)
func (i *Handler) GetLysandInstanceMetadata(c *fiber.Ctx) error {
m, err := i.instanceMetadataService.Ours(c.UserContext())
if err != nil {
return err
}
return c.JSON(m.ToLysand())
}

View file

@ -1,28 +0,0 @@
package meta_handler
import (
"github.com/Masterminds/semver"
"github.com/gofiber/fiber/v2"
"github.com/lysand-org/versia-go/config"
"github.com/lysand-org/versia-go/pkg/lysand"
)
func (i *Handler) GetLysandServerMetadata(c *fiber.Ctx) error {
return c.JSON(lysand.ServerMetadata{
// TODO: Get version from build linker flags
Version: semver.MustParse("0.0.0-dev"),
Name: config.C.InstanceName,
Description: config.C.InstanceDescription,
Website: lysand.URLFromStd(config.C.PublicAddress),
// TODO: Get more info
Moderators: nil,
Admins: nil,
Logo: nil,
Banner: nil,
SupportedExtensions: []string{},
Extensions: map[string]any{},
})
}

View file

@ -0,0 +1,51 @@
package user_handler
import (
"errors"
"fmt"
"github.com/gofiber/fiber/v2"
"github.com/lysand-org/versia-go/internal/api_schema"
"github.com/lysand-org/versia-go/pkg/webfinger"
"net"
"syscall"
)
func (i *Handler) SearchUser(c *fiber.Ctx) error {
var req api_schema.SearchUserRequest
if err := c.QueryParser(&req); err != nil {
return api_schema.ErrInvalidRequestBody(nil)
}
if err := i.bodyValidator.Validate(req); err != nil {
return err
}
u, err := i.userService.Search(c.UserContext(), req)
if err != nil {
// TODO: Move into service error
if errors.Is(err, syscall.ECONNREFUSED) {
return api_schema.ErrBadRequest(map[string]any{"reason": "Remote server is offline"})
}
if errors.Is(err, webfinger.ErrUserNotFound) {
return api_schema.ErrUserNotFound
}
var dnsErr *net.DNSError
if errors.As(err, &dnsErr) {
if dnsErr.IsNotFound {
return api_schema.ErrBadRequest(map[string]any{"reason": fmt.Sprintf("Could not resolve %s", dnsErr.Name)})
}
if dnsErr.IsTimeout {
return api_schema.ErrInternalServerError(map[string]any{"reason": "Local DNS server timed out"})
}
}
i.log.Error(err, "Failed to search for user", "username", req.Username)
return api_schema.ErrInternalServerError(nil)
}
return c.JSON((*api_schema.LysandUser)(u.ToLysand()))
}

View file

@ -8,9 +8,11 @@ import (
)
type Handler struct {
userService service.UserService
federationService service.FederationService
inboxService service.InboxService
requestSigner service.RequestSigner
userService service.UserService
inboxService service.InboxService
bodyValidator validators.BodyValidator
requestValidator validators.RequestValidator
@ -18,11 +20,13 @@ type Handler struct {
log logr.Logger
}
func New(userService service.UserService, federationService service.FederationService, inboxService service.InboxService, bodyValidator validators.BodyValidator, requestValidator validators.RequestValidator, log logr.Logger) *Handler {
func New(federationService service.FederationService, requestSigner service.RequestSigner, userService service.UserService, inboxService service.InboxService, bodyValidator validators.BodyValidator, requestValidator validators.RequestValidator, log logr.Logger) *Handler {
return &Handler{
userService: userService,
federationService: federationService,
inboxService: inboxService,
requestSigner: requestSigner,
userService: userService,
inboxService: inboxService,
bodyValidator: bodyValidator,
requestValidator: requestValidator,
@ -41,6 +45,7 @@ func (i *Handler) Register(r fiber.Router) {
r.Get("/api/app/users/:id", i.GetUser)
r.Post("/api/app/users/", i.CreateUser)
r.Get("/api/users/search", i.SearchUser)
r.Get("/api/users/:id", i.GetLysandUser)
r.Post("/api/users/:id/inbox", i.LysandInbox)
}

View file

@ -27,5 +27,5 @@ func (i *Handler) GetLysandUser(c *fiber.Ctx) error {
return api_schema.ErrNotFound(map[string]any{"id": parsedRequestedUserID})
}
return c.JSON(u.ToLysand())
return i.requestSigner.Sign(c, u.Signer, u.ToLysand())
}

View file

@ -1,8 +1,10 @@
package user_handler
import (
"errors"
"github.com/gofiber/fiber/v2"
"github.com/lysand-org/versia-go/config"
"github.com/lysand-org/versia-go/internal/api_schema"
"github.com/lysand-org/versia-go/internal/helpers"
"github.com/lysand-org/versia-go/pkg/webfinger"
)
@ -16,13 +18,19 @@ func (i *Handler) Webfinger(c *fiber.Ctx) error {
}
if userID.Domain != config.C.PublicAddress.Host {
return c.Status(fiber.StatusNotFound).JSON(webfinger.Response{
return c.Status(fiber.StatusBadRequest).JSON(webfinger.Response{
Error: helpers.StringPtr("The requested user is a remote user"),
})
}
wf, err := i.userService.GetWebfingerForUser(c.UserContext(), userID.ID)
if err != nil {
if errors.Is(err, api_schema.ErrUserNotFound) {
return c.Status(fiber.StatusNotFound).JSON(webfinger.Response{
Error: helpers.StringPtr("User could not be found"),
})
}
return c.Status(fiber.StatusInternalServerError).JSON(webfinger.Response{
Error: helpers.StringPtr("Failed to query user"),
})

View file

@ -36,7 +36,7 @@ func NewFollowRepositoryImpl(db *ent.Client, log logr.Logger, telemetry *unitel.
}
func (i FollowRepositoryImpl) GetByID(ctx context.Context, id uuid.UUID) (*entity.Follow, error) {
s := i.telemetry.StartSpan(ctx, "function", "repository/repo_impls.FollowRepositoryImpl.GetByID").
s := i.telemetry.StartSpan(ctx, "function", "repo_impls/FollowRepositoryImpl.GetByID").
AddAttribute("followID", id)
defer s.End()
ctx = s.Context()
@ -58,7 +58,7 @@ func (i FollowRepositoryImpl) GetByID(ctx context.Context, id uuid.UUID) (*entit
}
func (i FollowRepositoryImpl) Follow(ctx context.Context, follower, followee *entity.User) (*entity.Follow, error) {
s := i.telemetry.StartSpan(ctx, "function", "repository/repo_impls.FollowRepositoryImpl.Follow").
s := i.telemetry.StartSpan(ctx, "function", "repo_impls/FollowRepositoryImpl.Follow").
AddAttribute("follower", follower.URI).
AddAttribute("followee", followee.URI)
defer s.End()
@ -101,7 +101,7 @@ func (i FollowRepositoryImpl) Follow(ctx context.Context, follower, followee *en
}
func (i FollowRepositoryImpl) Unfollow(ctx context.Context, follower, followee *entity.User) error {
s := i.telemetry.StartSpan(ctx, "function", "repository/repo_impls.FollowRepositoryImpl.Unfollow").
s := i.telemetry.StartSpan(ctx, "function", "repo_impls/FollowRepositoryImpl.Unfollow").
AddAttribute("follower", follower.URI).
AddAttribute("followee", followee.URI)
defer s.End()
@ -121,7 +121,7 @@ func (i FollowRepositoryImpl) Unfollow(ctx context.Context, follower, followee *
}
func (i FollowRepositoryImpl) AcceptFollow(ctx context.Context, follower, followee *entity.User) error {
s := i.telemetry.StartSpan(ctx, "function", "repository/repo_impls.FollowRepositoryImpl.AcceptFollow").
s := i.telemetry.StartSpan(ctx, "function", "repo_impls/FollowRepositoryImpl.AcceptFollow").
AddAttribute("follower", follower.URI).
AddAttribute("followee", followee.URI)
defer s.End()
@ -141,7 +141,7 @@ func (i FollowRepositoryImpl) AcceptFollow(ctx context.Context, follower, follow
}
func (i FollowRepositoryImpl) RejectFollow(ctx context.Context, follower, followee *entity.User) error {
s := i.telemetry.StartSpan(ctx, "function", "repository/repo_impls.FollowRepositoryImpl.RejectFollow").
s := i.telemetry.StartSpan(ctx, "function", "repo_impls/FollowRepositoryImpl.RejectFollow").
AddAttribute("follower", follower.URI).
AddAttribute("followee", followee.URI)
defer s.End()

View file

@ -0,0 +1,62 @@
package repo_impls
import (
"context"
"git.devminer.xyz/devminer/unitel"
"github.com/go-logr/logr"
"github.com/lysand-org/versia-go/ent"
"github.com/lysand-org/versia-go/ent/instancemetadata"
"github.com/lysand-org/versia-go/internal/entity"
"github.com/lysand-org/versia-go/internal/repository"
"github.com/lysand-org/versia-go/internal/service"
"github.com/lysand-org/versia-go/pkg/lysand"
)
var _ repository.InstanceMetadataRepository = (*InstanceMetadataRepositoryImpl)(nil)
type InstanceMetadataRepositoryImpl struct {
federationService service.FederationService
db *ent.Client
log logr.Logger
telemetry *unitel.Telemetry
}
func NewInstanceMetadataRepositoryImpl(federationService service.FederationService, db *ent.Client, log logr.Logger, telemetry *unitel.Telemetry) repository.InstanceMetadataRepository {
return &InstanceMetadataRepositoryImpl{
federationService: federationService,
db: db,
log: log,
telemetry: telemetry,
}
}
func (i *InstanceMetadataRepositoryImpl) GetByHost(ctx context.Context, host string) (*entity.InstanceMetadata, error) {
s := i.telemetry.StartSpan(ctx, "function", "repo_impls/InstanceMetadataRepositoryImpl.GetByHost").
AddAttribute("host", host)
defer s.End()
ctx = s.Context()
m, err := i.db.InstanceMetadata.Query().
Where(instancemetadata.Host(host)).
WithAdmins().
WithModerators().
Only(ctx)
if err != nil {
return nil, err
}
return entity.NewInstanceMetadata(m)
}
func (i *InstanceMetadataRepositoryImpl) ImportFromLysandByURI(ctx context.Context, uri *lysand.URL) (*entity.InstanceMetadata, error) {
s := i.telemetry.StartSpan(ctx, "function", "repo_impls/InstanceMetadataRepositoryImpl.ImportFromLysandByURI").
AddAttribute("uri", uri.String())
defer s.End()
ctx = s.Context()
//i.federationService.
return nil, nil
}

View file

@ -15,32 +15,38 @@ type Factory[T any] func(db *ent.Client, log logr.Logger, telemetry *unitel.Tele
var _ repository.Manager = (*ManagerImpl)(nil)
type ManagerImpl struct {
users repository.UserRepository
notes repository.NoteRepository
follows repository.FollowRepository
users repository.UserRepository
notes repository.NoteRepository
follows repository.FollowRepository
instanceMetadata repository.InstanceMetadataRepository
uRFactory Factory[repository.UserRepository]
nRFactory Factory[repository.NoteRepository]
fRFactory Factory[repository.FollowRepository]
uRFactory Factory[repository.UserRepository]
nRFactory Factory[repository.NoteRepository]
fRFactory Factory[repository.FollowRepository]
imRFactory Factory[repository.InstanceMetadataRepository]
db *ent.Client
log logr.Logger
telemetry *unitel.Telemetry
}
func NewManagerImpl(db *ent.Client, telemetry *unitel.Telemetry, log logr.Logger, userRepositoryFunc Factory[repository.UserRepository], noteRepositoryFunc Factory[repository.NoteRepository], followRepositoryFunc Factory[repository.FollowRepository]) *ManagerImpl {
userRepository := userRepositoryFunc(db, log.WithName("users"), telemetry)
noteRepository := noteRepositoryFunc(db, log.WithName("notes"), telemetry)
followRepository := followRepositoryFunc(db, log.WithName("follows"), telemetry)
func NewManagerImpl(
db *ent.Client, telemetry *unitel.Telemetry, log logr.Logger,
userRepositoryFunc Factory[repository.UserRepository],
noteRepositoryFunc Factory[repository.NoteRepository],
followRepositoryFunc Factory[repository.FollowRepository],
instanceMetadataRepositoryFunc Factory[repository.InstanceMetadataRepository],
) *ManagerImpl {
return &ManagerImpl{
users: userRepository,
notes: noteRepository,
follows: followRepository,
users: userRepositoryFunc(db, log.WithName("users"), telemetry),
notes: noteRepositoryFunc(db, log.WithName("notes"), telemetry),
follows: followRepositoryFunc(db, log.WithName("follows"), telemetry),
instanceMetadata: instanceMetadataRepositoryFunc(db, log.WithName("instanceMetadata"), telemetry),
uRFactory: userRepositoryFunc,
nRFactory: noteRepositoryFunc,
fRFactory: followRepositoryFunc,
uRFactory: userRepositoryFunc,
nRFactory: noteRepositoryFunc,
fRFactory: followRepositoryFunc,
imRFactory: instanceMetadataRepositoryFunc,
db: db,
log: log,
@ -49,11 +55,17 @@ func NewManagerImpl(db *ent.Client, telemetry *unitel.Telemetry, log logr.Logger
}
func (i *ManagerImpl) withDB(db *ent.Client) *ManagerImpl {
return NewManagerImpl(db, i.telemetry, i.log, i.uRFactory, i.nRFactory, i.fRFactory)
return NewManagerImpl(
db, i.telemetry, i.log,
i.uRFactory,
i.nRFactory,
i.fRFactory,
i.imRFactory,
)
}
func (i *ManagerImpl) Atomic(ctx context.Context, fn func(ctx context.Context, tx repository.Manager) error) error {
s := i.telemetry.StartSpan(ctx, "function", "repository/repo_impls.ManagerImpl.Atomic")
s := i.telemetry.StartSpan(ctx, "function", "repo_impls/ManagerImpl.Atomic")
defer s.End()
ctx = s.Context()
@ -88,3 +100,7 @@ func (i *ManagerImpl) Notes() repository.NoteRepository {
func (i *ManagerImpl) Follows() repository.FollowRepository {
return i.follows
}
func (i *ManagerImpl) InstanceMetadata() repository.InstanceMetadataRepository {
return i.instanceMetadata
}

View file

@ -31,7 +31,7 @@ func NewNoteRepositoryImpl(db *ent.Client, log logr.Logger, telemetry *unitel.Te
}
func (i *NoteRepositoryImpl) NewNote(ctx context.Context, author *entity.User, content string, mentions []*entity.User) (*entity.Note, error) {
s := i.telemetry.StartSpan(ctx, "function", "repository/repo_impls.NoteRepositoryImpl.NewNote")
s := i.telemetry.StartSpan(ctx, "function", "repo_impls/NoteRepositoryImpl.NewNote")
defer s.End()
ctx = s.Context()
@ -63,7 +63,7 @@ func (i *NoteRepositoryImpl) NewNote(ctx context.Context, author *entity.User, c
}
func (i *NoteRepositoryImpl) ImportLysandNote(ctx context.Context, lNote *lysand.Note) (*entity.Note, error) {
s := i.telemetry.StartSpan(ctx, "function", "repository/repo_impls.NoteRepositoryImpl.ImportLysandNote")
s := i.telemetry.StartSpan(ctx, "function", "repo_impls/NoteRepositoryImpl.ImportLysandNote")
defer s.End()
ctx = s.Context()
@ -91,7 +91,7 @@ func (i *NoteRepositoryImpl) ImportLysandNote(ctx context.Context, lNote *lysand
}
func (i *NoteRepositoryImpl) GetByID(ctx context.Context, id uuid.UUID) (*entity.Note, error) {
s := i.telemetry.StartSpan(ctx, "function", "repository/repo_impls.NoteRepositoryImpl.LookupByIDOrUsername")
s := i.telemetry.StartSpan(ctx, "function", "repo_impls/NoteRepositoryImpl.LookupByIDOrUsername")
defer s.End()
ctx = s.Context()

View file

@ -4,6 +4,7 @@ import (
"context"
"crypto/ed25519"
"errors"
"github.com/lysand-org/versia-go/config"
"github.com/lysand-org/versia-go/internal/repository"
"github.com/lysand-org/versia-go/internal/service"
"golang.org/x/crypto/bcrypt"
@ -45,7 +46,7 @@ func NewUserRepositoryImpl(federationService service.FederationService, db *ent.
}
func (i *UserRepositoryImpl) NewUser(ctx context.Context, username, password string, priv ed25519.PrivateKey, pub ed25519.PublicKey) (*entity.User, error) {
s := i.telemetry.StartSpan(ctx, "function", "repository/repo_impls.UserRepositoryImpl.NewUser")
s := i.telemetry.StartSpan(ctx, "function", "repo_impls/UserRepositoryImpl.NewUser")
defer s.End()
ctx = s.Context()
@ -62,8 +63,10 @@ func (i *UserRepositoryImpl) NewUser(ctx context.Context, username, password str
SetURI(utils.UserAPIURL(uid).String()).
SetUsername(username).
SetPasswordHash(pwHash).
SetPublicKey(pub).
SetPrivateKey(priv).
SetPublicKey(pub).
SetPublicKeyAlgorithm("ed25519").
SetPublicKeyActor(utils.UserAPIURL(uid).String()).
SetInbox(utils.UserInboxAPIURL(uid).String()).
SetOutbox(utils.UserOutboxAPIURL(uid).String()).
SetFeatured(utils.UserFeaturedAPIURL(uid).String()).
@ -82,7 +85,7 @@ func (i *UserRepositoryImpl) NewUser(ctx context.Context, username, password str
}
func (i *UserRepositoryImpl) ImportLysandUserByURI(ctx context.Context, uri *lysand.URL) (*entity.User, error) {
s := i.telemetry.StartSpan(ctx, "function", "repository/repo_impls.UserRepositoryImpl.ImportLysandUserByURI")
s := i.telemetry.StartSpan(ctx, "function", "repo_impls/UserRepositoryImpl.ImportLysandUserByURI")
defer s.End()
ctx = s.Context()
@ -99,7 +102,9 @@ func (i *UserRepositoryImpl) ImportLysandUserByURI(ctx context.Context, uri *lys
SetUsername(lUser.Username).
SetNillableDisplayName(lUser.DisplayName).
SetBiography(lUser.Bio.String()).
SetPublicKey(lUser.PublicKey.PublicKey.ToStd()).
SetPublicKey(lUser.PublicKey.RawKey).
SetPublicKeyAlgorithm(lUser.PublicKey.Algorithm).
SetPublicKeyActor(lUser.PublicKey.Actor.String()).
SetIndexable(lUser.Indexable).
SetFields(lUser.Fields).
SetExtensions(lUser.Extensions).
@ -127,11 +132,66 @@ func (i *UserRepositoryImpl) ImportLysandUserByURI(ctx context.Context, uri *lys
return entity.NewUser(u)
}
func (i *UserRepositoryImpl) Resolve(ctx context.Context, uri *lysand.URL) (*entity.User, error) {
s := i.telemetry.StartSpan(ctx, "function", "repository/repo_impls.UserRepositoryImpl.Resolve")
func (i *UserRepositoryImpl) Discover(ctx context.Context, domain, username string) (*entity.User, error) {
s := i.telemetry.StartSpan(ctx, "function", "svc_impls/UserServiceImpl.Search").
AddAttribute("username", username).
AddAttribute("domain", domain)
defer s.End()
ctx = s.Context()
l := i.log.WithValues("domain", domain, "username", username)
// TODO: This *could* go wrong
if domain != config.C.Host {
l.V(2).Info("Discovering instance")
im, err := i.federationService.DiscoverInstance(ctx, domain)
if err != nil {
l.Error(err, "Failed to discover instance")
return nil, err
}
l = l.WithValues("host", im.Host)
l.V(2).Info("Discovering user")
wf, err := i.federationService.DiscoverUser(ctx, im.Host, username)
if err != nil {
l.Error(err, "Failed to discover user")
return nil, err
}
l.V(2).Info("Found remote user", "userURI", wf.URI)
u, err := i.Resolve(ctx, lysand.URLFromStd(wf.URI))
if err != nil {
l.Error(err, "Failed to resolve user")
return nil, err
}
return u, nil
}
l.V(2).Info("Finding local user")
u, err := i.GetLocalByUsername(ctx, username)
if err != nil {
l.Error(err, "Failed to find local user", "username", username)
return nil, err
}
l.V(2).Info("Found local user", "userURI", u.URI)
return u, nil
}
func (i *UserRepositoryImpl) Resolve(ctx context.Context, uri *lysand.URL) (*entity.User, error) {
s := i.telemetry.StartSpan(ctx, "function", "repo_impls/UserRepositoryImpl.Resolve")
defer s.End()
ctx = s.Context()
l := i.log.WithValues("uri", uri)
u, err := i.LookupByURI(ctx, uri)
if err != nil {
return nil, err
@ -139,24 +199,24 @@ func (i *UserRepositoryImpl) Resolve(ctx context.Context, uri *lysand.URL) (*ent
// check if the user is already imported
if u == nil {
i.log.V(2).Info("User not found in DB", "uri", uri)
l.V(2).Info("User not found in DB")
u, err := i.ImportLysandUserByURI(ctx, uri)
if err != nil {
i.log.Error(err, "Failed to import user", "uri", uri)
l.Error(err, "Failed to import user")
return nil, err
}
return u, nil
}
i.log.V(2).Info("User found in DB", "uri", uri)
l.V(2).Info("User found in DB")
return u, nil
}
func (i *UserRepositoryImpl) ResolveMultiple(ctx context.Context, uris []lysand.URL) ([]*entity.User, error) {
s := i.telemetry.StartSpan(ctx, "function", "repository/repo_impls.UserRepositoryImpl.ResolveMultiple")
s := i.telemetry.StartSpan(ctx, "function", "repo_impls/UserRepositoryImpl.ResolveMultiple")
defer s.End()
ctx = s.Context()
@ -168,25 +228,27 @@ func (i *UserRepositoryImpl) ResolveMultiple(ctx context.Context, uris []lysand.
// TODO: Refactor to use async imports using a work queue
outer:
for _, uri := range uris {
l := i.log.WithValues("uri", uri)
// check if the user is already imported
for _, u := range us {
if uri.String() == u.URI.String() {
i.log.V(2).Info("User found in DB", "uri", uri)
l.V(2).Info("User found in DB")
continue outer
}
}
i.log.V(2).Info("User not found in DB", "uri", uri)
l.V(2).Info("User not found in DB")
importedUser, err := i.ImportLysandUserByURI(ctx, &uri)
if err != nil {
i.log.Error(err, "Failed to import user", "uri", uri)
l.Error(err, "Failed to import user")
continue
}
i.log.V(2).Info("Imported user", "uri", uri)
l.V(2).Info("Imported user")
us = append(us, importedUser)
}
@ -195,10 +257,12 @@ outer:
}
func (i *UserRepositoryImpl) GetByID(ctx context.Context, uid uuid.UUID) (*entity.User, error) {
s := i.telemetry.StartSpan(ctx, "function", "repository/repo_impls.UserRepositoryImpl.GetByID")
s := i.telemetry.StartSpan(ctx, "function", "repo_impls/UserRepositoryImpl.GetByID")
defer s.End()
ctx = s.Context()
l := i.log.WithValues("id", uid)
u, err := i.db.User.Query().
Where(user.IDEQ(uid)).
WithAvatarImage().
@ -206,25 +270,27 @@ func (i *UserRepositoryImpl) GetByID(ctx context.Context, uid uuid.UUID) (*entit
Only(ctx)
if err != nil {
if !ent.IsNotFound(err) {
i.log.Error(err, "Failed to query user", "id", uid)
l.Error(err, "Failed to query user")
return nil, err
}
i.log.V(2).Info("User not found in DB", "id", uid)
l.V(2).Info("User not found in DB")
return nil, nil
}
i.log.V(2).Info("User found in DB", "id", uid)
l.V(2).Info("User found in DB")
return entity.NewUser(u)
}
func (i *UserRepositoryImpl) GetLocalByID(ctx context.Context, uid uuid.UUID) (*entity.User, error) {
s := i.telemetry.StartSpan(ctx, "function", "repository/repo_impls.UserRepositoryImpl.GetLocalByID")
s := i.telemetry.StartSpan(ctx, "function", "repo_impls/UserRepositoryImpl.GetLocalByID")
defer s.End()
ctx = s.Context()
l := i.log.WithValues("id", uid)
u, err := i.db.User.Query().
Where(user.And(user.ID(uid), user.IsRemote(false))).
WithAvatarImage().
@ -232,47 +298,77 @@ func (i *UserRepositoryImpl) GetLocalByID(ctx context.Context, uid uuid.UUID) (*
Only(ctx)
if err != nil {
if !ent.IsNotFound(err) {
i.log.Error(err, "Failed to query local user", "id", uid)
l.Error(err, "Failed to query local user")
return nil, err
}
i.log.V(2).Info("Local user not found in DB", "id", uid)
l.V(2).Info("Local user not found in DB")
return nil, nil
}
i.log.V(2).Info("Local user found in DB", "id", uid)
l.V(2).Info("Local user found in DB", "uri", u.URI)
return entity.NewUser(u)
}
func (i *UserRepositoryImpl) GetLocalByUsername(ctx context.Context, username string) (*entity.User, error) {
s := i.telemetry.StartSpan(ctx, "function", "repo_impls/UserRepositoryImpl.GetLocalByUsername")
defer s.End()
ctx = s.Context()
l := i.log.WithValues("username", username)
u, err := i.db.User.Query().
Where(user.And(user.Username(username), user.IsRemote(false))).
WithAvatarImage().
WithHeaderImage().
Only(ctx)
if err != nil {
if !ent.IsNotFound(err) {
l.Error(err, "Failed to query local user")
return nil, err
}
l.V(2).Info("Local user not found in DB")
return nil, nil
}
l.V(2).Info("Local user found in DB", "uri", u.URI)
return entity.NewUser(u)
}
func (i *UserRepositoryImpl) LookupByURI(ctx context.Context, uri *lysand.URL) (*entity.User, error) {
s := i.telemetry.StartSpan(ctx, "function", "repository/repo_impls.UserRepositoryImpl.LookupByURI")
s := i.telemetry.StartSpan(ctx, "function", "repo_impls/UserRepositoryImpl.LookupByURI")
defer s.End()
ctx = s.Context()
l := i.log.WithValues("uri", uri)
// check if the user is already imported
u, err := i.db.User.Query().
Where(user.URI(uri.String())).
Only(ctx)
if err != nil {
if !ent.IsNotFound(err) {
i.log.Error(err, "Failed to query user", "uri", uri)
l.Error(err, "Failed to query user")
return nil, err
}
i.log.V(2).Info("User not found in DB", "uri", uri)
l.V(2).Info("User not found in DB")
return nil, nil
}
i.log.V(2).Info("User found in DB", "uri", uri)
l.V(2).Info("User found in DB")
return entity.NewUser(u)
}
func (i *UserRepositoryImpl) LookupByURIs(ctx context.Context, uris []lysand.URL) ([]*entity.User, error) {
s := i.telemetry.StartSpan(ctx, "function", "repository/repo_impls.UserRepositoryImpl.LookupByURIs")
s := i.telemetry.StartSpan(ctx, "function", "repo_impls/UserRepositoryImpl.LookupByURIs")
defer s.End()
ctx = s.Context()
@ -292,7 +388,7 @@ func (i *UserRepositoryImpl) LookupByURIs(ctx context.Context, uris []lysand.URL
}
func (i *UserRepositoryImpl) LookupByIDOrUsername(ctx context.Context, idOrUsername string) (*entity.User, error) {
s := i.telemetry.StartSpan(ctx, "function", "repository/repo_impls.UserRepositoryImpl.LookupByIDOrUsername")
s := i.telemetry.StartSpan(ctx, "function", "repo_impls/UserRepositoryImpl.LookupByIDOrUsername")
defer s.End()
ctx = s.Context()
@ -303,6 +399,8 @@ func (i *UserRepositoryImpl) LookupByIDOrUsername(ctx context.Context, idOrUsern
preds = append(preds, user.UsernameEQ(idOrUsername))
}
l := i.log.WithValues("idOrUsername", idOrUsername)
u, err := i.db.User.Query().
Where(preds...).
WithAvatarImage().
@ -310,16 +408,16 @@ func (i *UserRepositoryImpl) LookupByIDOrUsername(ctx context.Context, idOrUsern
Only(ctx)
if err != nil {
if !ent.IsNotFound(err) {
i.log.Error(err, "Failed to query user", "idOrUsername", idOrUsername)
l.Error(err, "Failed to query user")
return nil, err
}
i.log.V(2).Info("User not found in DB", "idOrUsername", idOrUsername)
l.V(2).Info("User not found in DB")
return nil, nil
}
i.log.V(2).Info("User found in DB", "idOrUsername", idOrUsername, "id", u.ID)
l.V(2).Info("User found in DB", "id", u.ID)
return entity.NewUser(u)
}

View file

@ -15,6 +15,9 @@ type UserRepository interface {
GetByID(ctx context.Context, id uuid.UUID) (*entity.User, error)
GetLocalByID(ctx context.Context, id uuid.UUID) (*entity.User, error)
GetLocalByUsername(ctx context.Context, username string) (*entity.User, error)
Discover(ctx context.Context, host, username string) (*entity.User, error)
Resolve(ctx context.Context, uri *lysand.URL) (*entity.User, error)
ResolveMultiple(ctx context.Context, uris []lysand.URL) ([]*entity.User, error)
@ -40,10 +43,16 @@ type NoteRepository interface {
GetByID(ctx context.Context, idOrUsername uuid.UUID) (*entity.Note, error)
}
type InstanceMetadataRepository interface {
GetByHost(ctx context.Context, host string) (*entity.InstanceMetadata, error)
ImportFromLysandByURI(ctx context.Context, uri *lysand.URL) (*entity.InstanceMetadata, error)
}
type Manager interface {
Atomic(ctx context.Context, fn func(ctx context.Context, tx Manager) error) error
Users() UserRepository
Notes() NoteRepository
Follows() FollowRepository
InstanceMetadata() InstanceMetadataRepository
}

View file

@ -2,6 +2,7 @@ package service
import (
"context"
"github.com/gofiber/fiber/v2"
"github.com/lysand-org/versia-go/internal/repository"
"github.com/google/uuid"
@ -19,11 +20,16 @@ type UserService interface {
GetUserByID(ctx context.Context, id uuid.UUID) (*entity.User, error)
GetWebfingerForUser(ctx context.Context, userID string) (*webfinger.User, error)
Search(ctx context.Context, req api_schema.SearchUserRequest) (*entity.User, error)
}
type FederationService interface {
SendToInbox(ctx context.Context, author *entity.User, target *entity.User, object any) ([]byte, error)
GetUser(ctx context.Context, uri *lysand.URL) (*lysand.User, error)
DiscoverUser(ctx context.Context, baseURL, username string) (*webfinger.User, error)
DiscoverInstance(ctx context.Context, baseURL string) (*lysand.InstanceMetadata, error)
}
type InboxService interface {
@ -44,6 +50,14 @@ type FollowService interface {
ImportLysandFollow(ctx context.Context, lFollow *lysand.Follow) (*entity.Follow, error)
}
type InstanceMetadataService interface {
Ours(ctx context.Context) (*entity.InstanceMetadata, error)
}
type TaskService interface {
ScheduleTask(ctx context.Context, type_ string, data any) error
}
type RequestSigner interface {
Sign(c *fiber.Ctx, signer lysand.Signer, body any) error
}

View file

@ -18,29 +18,31 @@ import (
var _ service.InboxService = (*InboxServiceImpl)(nil)
type InboxServiceImpl struct {
repositories repository.Manager
federationService service.FederationService
repositories repository.Manager
telemetry *unitel.Telemetry
log logr.Logger
}
func NewInboxService(repositories repository.Manager, federationService service.FederationService, telemetry *unitel.Telemetry, log logr.Logger) *InboxServiceImpl {
func NewInboxService(federationService service.FederationService, repositories repository.Manager, telemetry *unitel.Telemetry, log logr.Logger) *InboxServiceImpl {
return &InboxServiceImpl{
repositories: repositories,
federationService: federationService,
telemetry: telemetry,
log: log,
repositories: repositories,
telemetry: telemetry,
log: log,
}
}
func (i InboxServiceImpl) WithRepositories(repositories repository.Manager) service.InboxService {
return NewInboxService(repositories, i.federationService, i.telemetry, i.log)
return NewInboxService(i.federationService, repositories, i.telemetry, i.log)
}
func (i InboxServiceImpl) Handle(ctx context.Context, obj any, userId uuid.UUID) error {
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.InboxServiceImpl.Handle")
s := i.telemetry.StartSpan(ctx, "function", "svc_impls/InboxServiceImpl.Handle")
defer s.End()
ctx = s.Context()
@ -87,7 +89,7 @@ func (i InboxServiceImpl) Handle(ctx context.Context, obj any, userId uuid.UUID)
}
func (i InboxServiceImpl) handleFollow(ctx context.Context, o lysand.Follow, u *entity.User) error {
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.InboxServiceImpl.handleFollow")
s := i.telemetry.StartSpan(ctx, "function", "svc_impls/InboxServiceImpl.handleFollow")
defer s.End()
ctx = s.Context()
@ -129,7 +131,7 @@ func (i InboxServiceImpl) handleFollow(ctx context.Context, o lysand.Follow, u *
}
func (i InboxServiceImpl) handleNote(ctx context.Context, o lysand.Note, u *entity.User) error {
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.InboxServiceImpl.handleNote")
s := i.telemetry.StartSpan(ctx, "function", "svc_impls/InboxServiceImpl.handleNote")
defer s.End()
ctx = s.Context()

View file

@ -1,17 +1,34 @@
package svc_impls
import (
"bytes"
"context"
"crypto/rand"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"git.devminer.xyz/devminer/unitel"
"github.com/go-logr/logr"
"github.com/lysand-org/versia-go/internal/entity"
"github.com/lysand-org/versia-go/internal/service"
"github.com/lysand-org/versia-go/pkg/lysand"
versiacrypto "github.com/lysand-org/versia-go/pkg/lysand/crypto"
"github.com/lysand-org/versia-go/pkg/protoretry"
"github.com/lysand-org/versia-go/pkg/webfinger"
"net/http"
"net/url"
)
var _ service.FederationService = (*FederationServiceImpl)(nil)
var (
_ service.FederationService = (*FederationServiceImpl)(nil)
ErrSignatureValidationFailed = errors.New("signature validation failed")
)
type FederationServiceImpl struct {
httpC *protoretry.Client
federationClient *lysand.FederationClient
telemetry *unitel.Telemetry
@ -19,38 +36,139 @@ type FederationServiceImpl struct {
log logr.Logger
}
func NewFederationServiceImpl(federationClient *lysand.FederationClient, telemetry *unitel.Telemetry, log logr.Logger) *FederationServiceImpl {
func NewFederationServiceImpl(httpClient *http.Client, federationClient *lysand.FederationClient, telemetry *unitel.Telemetry, log logr.Logger) *FederationServiceImpl {
return &FederationServiceImpl{
httpC: protoretry.New(httpClient),
federationClient: federationClient,
telemetry: telemetry,
log: log,
}
}
func (i FederationServiceImpl) SendToInbox(ctx context.Context, author *entity.User, target *entity.User, object any) ([]byte, error) {
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.FederationServiceImpl.SendToInbox")
func (i *FederationServiceImpl) GetUser(ctx context.Context, uri *lysand.URL) (*lysand.User, error) {
s := i.telemetry.StartSpan(ctx, "function", "svc_impls/FederationServiceImpl.GetUser").
AddAttribute("userURI", uri.String())
defer s.End()
ctx = s.Context()
response, err := i.federationClient.SendToInbox(ctx, author.Signer, target.ToLysand(), object)
body, resp, err := i.httpC.GET(ctx, uri.ToStd())
if err != nil {
i.log.Error(err, "Failed to send to inbox", "author", author.ID, "target", target.ID)
return response, err
}
return response, nil
}
func (i FederationServiceImpl) GetUser(ctx context.Context, uri *lysand.URL) (*lysand.User, error) {
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.FederationServiceImpl.GetUser")
defer s.End()
ctx = s.Context()
u, err := i.federationClient.GetUser(ctx, uri.ToStd())
if err != nil {
i.log.Error(err, "Failed to fetch remote user", "uri", uri)
s.SetSimpleStatus(unitel.Error, err.Error())
return nil, err
}
u := &lysand.User{}
if err := json.Unmarshal(body, u); err != nil {
s.SetSimpleStatus(unitel.Error, err.Error())
return nil, err
}
fedHeaders, err := lysand.ExtractFederationHeaders(resp.Header)
if err != nil {
s.SetSimpleStatus(unitel.Error, err.Error())
return nil, err
}
v := lysand.Verifier{PublicKey: u.PublicKey.Key.Key}
if !v.Verify("GET", uri.ToStd(), body, fedHeaders) {
s.SetSimpleStatus(unitel.Error, ErrSignatureValidationFailed.Error())
i.log.V(1).Error(ErrSignatureValidationFailed, "signature validation failed", "user", u.URI.String())
return nil, ErrSignatureValidationFailed
}
s.SetSimpleStatus(unitel.Ok, "")
i.log.V(2).Info("signature verification succeeded", "user", u.URI.String())
return u, nil
}
func (i *FederationServiceImpl) DiscoverUser(ctx context.Context, baseURL, username string) (*webfinger.User, error) {
s := i.telemetry.StartSpan(ctx, "function", "svc_impls/FederationServiceImpl.DiscoverUser").
AddAttribute("baseURL", baseURL).
AddAttribute("username", username)
defer s.End()
ctx = s.Context()
wf, err := webfinger.Discover(i.httpC, ctx, baseURL, username)
if err != nil {
s.SetSimpleStatus(unitel.Error, err.Error())
return nil, err
}
s.SetSimpleStatus(unitel.Ok, "")
return wf, nil
}
func (i *FederationServiceImpl) DiscoverInstance(ctx context.Context, baseURL string) (*lysand.InstanceMetadata, error) {
s := i.telemetry.StartSpan(ctx, "function", "svc_impls/FederationServiceImpl.DiscoverInstance").
AddAttribute("baseURL", baseURL)
defer s.End()
ctx = s.Context()
body, resp, err := i.httpC.GET(ctx, &url.URL{Scheme: "https", Host: baseURL, Path: "/.well-known/versia"})
if err != nil {
s.SetSimpleStatus(unitel.Error, err.Error())
return nil, err
} else if resp.StatusCode >= http.StatusBadRequest {
s.SetSimpleStatus(unitel.Error, fmt.Sprintf("unexpected response code: %d", resp.StatusCode))
return nil, &lysand.ResponseError{StatusCode: resp.StatusCode, URL: resp.Request.URL}
}
var metadata lysand.InstanceMetadata
if err := json.Unmarshal(body, &metadata); err != nil {
s.SetSimpleStatus(unitel.Error, err.Error())
return nil, err
}
s.SetSimpleStatus(unitel.Ok, "")
return &metadata, nil
}
func (i *FederationServiceImpl) SendToInbox(ctx context.Context, author *entity.User, user *entity.User, object any) ([]byte, error) {
s := i.telemetry.StartSpan(ctx, "function", "svc_impls/FederationServiceImpl.SendToInbox").
SetUser(uint64(author.ID.ID()), author.Username, "", "").
AddAttribute("author", author.ID).
AddAttribute("authorURI", author.URI).
AddAttribute("target", user.ID).
AddAttribute("targetURI", user.URI)
defer s.End()
ctx = s.Context()
uri := user.Inbox.ToStd()
body, err := json.Marshal(object)
if err != nil {
s.SetSimpleStatus(unitel.Error, err.Error())
return nil, err
}
nonce := make([]byte, 32)
if _, err := rand.Read(nonce); err != nil {
s.SetSimpleStatus(unitel.Error, err.Error())
return nil, err
}
sigData := lysand.NewSignatureData("POST", base64.StdEncoding.EncodeToString(nonce), uri, versiacrypto.SHA256(body))
sig := author.Signer.Sign(*sigData)
req, err := http.NewRequestWithContext(ctx, "POST", uri.String(), bytes.NewReader(body))
if err != nil {
s.SetSimpleStatus(unitel.Error, err.Error())
return nil, err
}
sig.Inject(req.Header)
body, _, err = i.httpC.DoReq(req)
if err != nil {
s.SetSimpleStatus(unitel.Error, err.Error())
i.log.Error(err, "Failed to send to inbox", "author", author.URI, "target", user.URI)
return nil, err
}
s.SetSimpleStatus(unitel.Ok, "")
return body, nil
}

View file

@ -33,7 +33,7 @@ func NewFollowServiceImpl(federationService service.FederationService, repositor
}
func (i FollowServiceImpl) NewFollow(ctx context.Context, follower, followee *entity.User) (*entity.Follow, error) {
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.FollowServiceImpl.NewFollow").
s := i.telemetry.StartSpan(ctx, "function", "svc_impls/FollowServiceImpl.NewFollow").
AddAttribute("follower", follower.URI).
AddAttribute("followee", followee.URI)
defer s.End()
@ -54,7 +54,7 @@ func (i FollowServiceImpl) NewFollow(ctx context.Context, follower, followee *en
}
func (i FollowServiceImpl) GetFollow(ctx context.Context, id uuid.UUID) (*entity.Follow, error) {
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.FollowServiceImpl.GetFollow").
s := i.telemetry.StartSpan(ctx, "function", "svc_impls/FollowServiceImpl.GetFollow").
AddAttribute("followID", id)
defer s.End()
ctx = s.Context()
@ -70,7 +70,7 @@ func (i FollowServiceImpl) GetFollow(ctx context.Context, id uuid.UUID) (*entity
}
func (i FollowServiceImpl) ImportLysandFollow(ctx context.Context, lFollow *lysand.Follow) (*entity.Follow, error) {
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.FollowServiceImpl.ImportLysandFollow").
s := i.telemetry.StartSpan(ctx, "function", "svc_impls/FollowServiceImpl.ImportLysandFollow").
AddAttribute("uri", lFollow.URI.String())
defer s.End()
ctx = s.Context()

View file

@ -0,0 +1,52 @@
package svc_impls
import (
"context"
"github.com/lysand-org/versia-go/config"
"github.com/lysand-org/versia-go/ent"
"github.com/lysand-org/versia-go/internal/repository"
"github.com/lysand-org/versia-go/internal/service"
"git.devminer.xyz/devminer/unitel"
"github.com/go-logr/logr"
"github.com/lysand-org/versia-go/internal/entity"
)
var _ service.InstanceMetadataService = (*InstanceMetadataServiceImpl)(nil)
type InstanceMetadataServiceImpl struct {
federationService service.FederationService
repositories repository.Manager
telemetry *unitel.Telemetry
log logr.Logger
}
func NewInstanceMetadataServiceImpl(federationService service.FederationService, repositories repository.Manager, telemetry *unitel.Telemetry, log logr.Logger) *InstanceMetadataServiceImpl {
return &InstanceMetadataServiceImpl{
federationService: federationService,
repositories: repositories,
telemetry: telemetry,
log: log,
}
}
func (i InstanceMetadataServiceImpl) Ours(ctx context.Context) (*entity.InstanceMetadata, error) {
s := i.telemetry.StartSpan(ctx, "function", "svc_impls/InstanceMetadataServiceImpl.Ours")
defer s.End()
ctx = s.Context()
m, err := i.repositories.InstanceMetadata().GetByHost(ctx, config.C.Host)
if err != nil {
if ent.IsNotFound(err) {
panic("could not find our own instance metadata")
}
return nil, err
}
return m, nil
}

View file

@ -39,7 +39,7 @@ func NewNoteServiceImpl(federationService service.FederationService, taskService
}
func (i NoteServiceImpl) CreateNote(ctx context.Context, req api_schema.CreateNoteRequest) (*entity.Note, error) {
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.NoteServiceImpl.CreateNote")
s := i.telemetry.StartSpan(ctx, "function", "svc_impls/NoteServiceImpl.CreateNote")
defer s.End()
ctx = s.Context()
@ -82,7 +82,7 @@ func (i NoteServiceImpl) CreateNote(ctx context.Context, req api_schema.CreateNo
}
func (i NoteServiceImpl) GetNote(ctx context.Context, id uuid.UUID) (*entity.Note, error) {
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.NoteServiceImpl.GetUserByID")
s := i.telemetry.StartSpan(ctx, "function", "svc_impls/NoteServiceImpl.GetUserByID")
defer s.End()
ctx = s.Context()
@ -90,7 +90,7 @@ func (i NoteServiceImpl) GetNote(ctx context.Context, id uuid.UUID) (*entity.Not
}
func (i NoteServiceImpl) ImportLysandNote(ctx context.Context, lNote *lysand.Note) (*entity.Note, error) {
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.NoteServiceImpl.ImportLysandNote")
s := i.telemetry.StartSpan(ctx, "function", "svc_impls/NoteServiceImpl.ImportLysandNote")
defer s.End()
ctx = s.Context()

View file

@ -0,0 +1,63 @@
package svc_impls
import (
"crypto/rand"
"encoding/base64"
"encoding/json"
"git.devminer.xyz/devminer/unitel"
"github.com/go-logr/logr"
"github.com/gofiber/fiber/v2"
"github.com/lysand-org/versia-go/internal/service"
"github.com/lysand-org/versia-go/pkg/lysand"
versiacrypto "github.com/lysand-org/versia-go/pkg/lysand/crypto"
"net/url"
)
var _ service.RequestSigner = (*RequestSignerImpl)(nil)
type RequestSignerImpl struct {
telemetry *unitel.Telemetry
log logr.Logger
}
func NewRequestSignerImpl(telemetry *unitel.Telemetry, log logr.Logger) *RequestSignerImpl {
return &RequestSignerImpl{
telemetry: telemetry,
log: log,
}
}
func (i *RequestSignerImpl) Sign(c *fiber.Ctx, signer lysand.Signer, body any) error {
s := i.telemetry.StartSpan(c.UserContext(), "function", "svc_impls/RequestSignerImpl.Sign")
defer s.End()
j, err := json.Marshal(body)
if err != nil {
return err
}
rawNonce := make([]byte, 64)
if _, err := rand.Read(rawNonce); err != nil {
return err
}
nonce := base64.StdEncoding.EncodeToString(rawNonce)
uri, err := url.ParseRequestURI(string(c.Request().RequestURI()))
if err != nil {
return err
}
digest := versiacrypto.SHA256(j)
d := lysand.NewSignatureData(c.Method(), nonce, uri, digest)
signed := signer.Sign(*d)
for k, v := range signed.Headers() {
c.Set(k, v)
}
i.log.V(2).Info("signed response", "digest", base64.StdEncoding.EncodeToString(digest), "nonce", nonce)
return c.Send(j)
}

View file

@ -28,7 +28,7 @@ func NewTaskServiceImpl(client *taskqueue.Client, telemetry *unitel.Telemetry, l
}
func (i TaskServiceImpl) ScheduleTask(ctx context.Context, type_ string, data any) error {
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.TaskServiceImpl.ScheduleTask")
s := i.telemetry.StartSpan(ctx, "function", "svc_impls/TaskServiceImpl.ScheduleTask")
defer s.End()
ctx = s.Context()

View file

@ -4,7 +4,7 @@ import (
"context"
"crypto/ed25519"
"crypto/rand"
"fmt"
"github.com/lysand-org/versia-go/internal/api_schema"
"github.com/lysand-org/versia-go/internal/repository"
"github.com/lysand-org/versia-go/internal/service"
"net/url"
@ -45,7 +45,7 @@ func (i UserServiceImpl) WithRepositories(repositories repository.Manager) servi
}
func (i UserServiceImpl) NewUser(ctx context.Context, username, password string) (*entity.User, error) {
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.UserServiceImpl.NewUser")
s := i.telemetry.StartSpan(ctx, "function", "svc_impls/UserServiceImpl.NewUser")
defer s.End()
ctx = s.Context()
@ -73,7 +73,7 @@ func (i UserServiceImpl) NewUser(ctx context.Context, username, password string)
}
func (i UserServiceImpl) GetUserByID(ctx context.Context, id uuid.UUID) (*entity.User, error) {
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.UserServiceImpl.GetUserByID")
s := i.telemetry.StartSpan(ctx, "function", "svc_impls/UserServiceImpl.GetUserByID")
defer s.End()
ctx = s.Context()
@ -81,7 +81,7 @@ func (i UserServiceImpl) GetUserByID(ctx context.Context, id uuid.UUID) (*entity
}
func (i UserServiceImpl) GetWebfingerForUser(ctx context.Context, userID string) (*webfinger.User, error) {
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.UserServiceImpl.GetWebfingerForUser")
s := i.telemetry.StartSpan(ctx, "function", "svc_impls/UserServiceImpl.GetWebfingerForUser")
defer s.End()
ctx = s.Context()
@ -90,7 +90,7 @@ func (i UserServiceImpl) GetWebfingerForUser(ctx context.Context, userID string)
return nil, err
}
if u == nil {
return nil, fmt.Errorf("user not found")
return nil, api_schema.ErrUserNotFound
}
wf := &webfinger.User{
@ -120,3 +120,25 @@ func (i UserServiceImpl) GetWebfingerForUser(ctx context.Context, userID string)
return wf, nil
}
func (i UserServiceImpl) Search(ctx context.Context, req api_schema.SearchUserRequest) (u *entity.User, err error) {
s := i.telemetry.StartSpan(ctx, "function", "svc_impls/UserServiceImpl.Search").
AddAttribute("username", req.Username)
defer s.End()
ctx = s.Context()
domain := ""
if req.Domain != nil {
domain = *req.Domain
}
err = i.repositories.Atomic(ctx, func(ctx context.Context, tx repository.Manager) error {
var err error
if u, err = i.repositories.Users().Discover(ctx, domain, req.Username); err != nil {
return err
}
return nil
})
return
}

View file

@ -24,6 +24,10 @@ func (t *Handler) FederateNote(ctx context.Context, data FederateNoteData) error
if err != nil {
return err
}
if n == nil {
t.log.V(-1).Info("Could not find note", "id", data.NoteID)
return nil
}
for _, uu := range n.Mentions {
if !uu.IsRemote {

32
internal/utils/fiber.go Normal file
View file

@ -0,0 +1,32 @@
package utils
import (
"bytes"
"github.com/gofiber/fiber/v2"
"github.com/valyala/fasthttp/fasthttpadaptor"
"io"
"net/http"
)
func ConvertToStdRequest(c *fiber.Ctx) (*http.Request, error) {
stdReq := &http.Request{}
if err := fasthttpadaptor.ConvertRequest(c.Context(), stdReq, true); err != nil {
return nil, err
}
return stdReq, nil
}
func CopyBody(req *http.Request) ([]byte, error) {
body, err := io.ReadAll(req.Body)
if err != nil {
return nil, err
}
if err := req.Body.Close(); err != nil {
return nil, err
}
req.Body = io.NopCloser(bytes.NewBuffer(body))
return body, nil
}

View file

@ -73,3 +73,23 @@ func NoteAPIURL(uuid uuid.UUID) *lysand.URL {
newPath := &url.URL{Path: fmt.Sprintf("/api/notes/%s/", uuid.String())}
return lysand.URLFromStd(config.C.PublicAddress.ResolveReference(newPath))
}
func InstanceMetadataAPIURL() *lysand.URL {
newPath := &url.URL{Path: "/.well-known/versia/"}
return lysand.URLFromStd(config.C.PublicAddress.ResolveReference(newPath))
}
func InstanceMetadataAdminsAPIURL() *lysand.URL {
newPath := &url.URL{Path: "/.well-known/versia/admins/"}
return lysand.URLFromStd(config.C.PublicAddress.ResolveReference(newPath))
}
func InstanceMetadataModeratorsAPIURL() *lysand.URL {
newPath := &url.URL{Path: "/.well-known/versia/moderators/"}
return lysand.URLFromStd(config.C.PublicAddress.ResolveReference(newPath))
}
func SharedInboxAPIURL() *lysand.URL {
newPath := &url.URL{Path: "/api/inbox/"}
return lysand.URLFromStd(config.C.PublicAddress.ResolveReference(newPath))
}

View file

@ -2,8 +2,10 @@ package val_impls
import (
"errors"
"github.com/lysand-org/versia-go/ent/schema"
"github.com/lysand-org/versia-go/internal/validators"
"reflect"
"regexp"
"strings"
"github.com/go-logr/logr"
@ -11,11 +13,20 @@ import (
universal_translator "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
en_translations "github.com/go-playground/validator/v10/translations/en"
"github.com/lysand-org/versia-go/ent/schema"
"github.com/lysand-org/versia-go/internal/api_schema"
)
var _ validators.BodyValidator = (*BodyValidatorImpl)(nil)
type bodyValidator struct {
Translated string
Validate func(fl validator.FieldLevel) bool
}
var (
_ validators.BodyValidator = (*BodyValidatorImpl)(nil)
fullUserRegex = regexp.MustCompile("^@([a-z0-9_-]+)(?:@([a-zA-Z0-1-_.]+\\.[a-zA-Z0-9-z]+(?::[0-9]+)?))?$")
domainRegex = regexp.MustCompile("^[a-zA-Z0-9-_.]+.[a-zA-Z0-9-z]+(?::[0-9]+)?$")
)
type BodyValidatorImpl struct {
validator *validator.Validate
@ -28,13 +39,13 @@ type BodyValidatorImpl struct {
func NewBodyValidator(log logr.Logger) *BodyValidatorImpl {
en := en_locale.New()
translator := universal_translator.New(en, en)
trans, ok := translator.GetTranslator("en")
enTranslator, ok := translator.GetTranslator("en")
if !ok {
panic("failed to get \"en\" translator")
}
validate := validator.New(validator.WithRequiredStructEnabled())
if err := en_translations.RegisterDefaultTranslations(validate, trans); err != nil {
if err := en_translations.RegisterDefaultTranslations(validate, enTranslator); err != nil {
panic("failed to register default translations")
}
@ -46,25 +57,65 @@ func NewBodyValidator(log logr.Logger) *BodyValidatorImpl {
return name
})
if err := validate.RegisterValidation("username_regex", func(fl validator.FieldLevel) bool {
return schema.ValidateUsername(fl.Field().String()) == nil
}); err != nil {
panic("failed to register username_regex validator")
bodyValidators := map[string]bodyValidator{
"username_regex": {
Translated: "{0} must match '^[a-z0-9_-]+$'!",
Validate: func(fl validator.FieldLevel) bool {
return schema.ValidateUsername(fl.Field().String()) == nil
},
},
"full_user_regex": {
Translated: "{0} must match '^@[a-z0-9_-]+$' or '^@[a-z0-9_-]+@[a-zA-Z0-1-_.]+\\.[a-zA-Z0-9-z]+(?::[0-9]+)?))?$'",
Validate: func(fl validator.FieldLevel) bool {
f := fl.Field()
if f.Type().String() == "string" {
return fullUserRegex.Match([]byte(f.String()))
}
return false
},
},
"domain_regex": {
Translated: "{0} must match '^[a-zA-Z0-9-_.]+.[a-zA-Z0-9-z]+(?::[0-9]+)?$'",
Validate: func(fl validator.FieldLevel) bool {
f := fl.Field()
t := f.Type().String()
if t == "string" {
return domainRegex.Match([]byte(f.String()))
}
log.V(-1).Info("got wrong type: %s\n", t)
return false
},
},
}
if err := validate.RegisterTranslation("username_regex", trans, func(ut universal_translator.Translator) error {
return trans.Add("user_regex", "{0} must match '^[a-z0-9_-]+$'!", true)
}, func(ut universal_translator.Translator, fe validator.FieldError) string {
t, _ := ut.T("user_regex", fe.Field())
return t
}); err != nil {
panic("failed to register user_regex translation")
for identifier, v := range bodyValidators {
if err := validate.RegisterValidation(identifier, v.Validate); err != nil {
log.Error(err, "failed to register validator", "identifier", identifier)
}
register := func(ut universal_translator.Translator) error {
return enTranslator.Add(identifier, v.Translated, true)
}
translate := func(ut universal_translator.Translator, fe validator.FieldError) string {
t, _ := ut.T(identifier, fe.Field())
return t
}
if err := validate.RegisterTranslation(identifier, enTranslator, register, translate); err != nil {
log.Error(err, "failed to register validator translator", "identifier", identifier)
}
}
return &BodyValidatorImpl{
validator: validate,
translator: translator,
enTranslator: trans,
enTranslator: enTranslator,
log: log,
}
}

View file

@ -1,17 +1,15 @@
package val_impls
import (
"bytes"
"context"
"errors"
"git.devminer.xyz/devminer/unitel"
"github.com/go-logr/logr"
"github.com/gofiber/fiber/v2"
"github.com/lysand-org/versia-go/internal/repository"
"github.com/lysand-org/versia-go/internal/utils"
"github.com/lysand-org/versia-go/internal/validators"
"github.com/lysand-org/versia-go/pkg/lysand"
"github.com/valyala/fasthttp/fasthttpadaptor"
"io"
"net/http"
)
@ -38,7 +36,7 @@ func NewRequestValidator(repositories repository.Manager, telemetry *unitel.Tele
}
func (i RequestValidatorImpl) Validate(ctx context.Context, r *http.Request) error {
s := i.telemetry.StartSpan(ctx, "function", "validator/val_impls.RequestValidatorImpl.Validate")
s := i.telemetry.StartSpan(ctx, "function", "val_impls/RequestValidatorImpl.Validate")
defer s.End()
ctx = s.Context()
@ -55,13 +53,13 @@ func (i RequestValidatorImpl) Validate(ctx context.Context, r *http.Request) err
return err
}
body, err := copyBody(r)
body, err := utils.CopyBody(r)
if err != nil {
return err
}
if !(lysand.Verifier{PublicKey: user.PublicKey}).Verify(r.Method, r.URL, body, fedHeaders) {
i.log.Info("signature verification failed", "user", user.URI, "url", r.URL.Path)
if !(lysand.Verifier{PublicKey: user.PublicKey.Key}).Verify(r.Method, r.URL, body, fedHeaders) {
i.log.WithCallDepth(1).Info("signature verification failed", "user", user.URI, "url", r.URL.Path)
s.CaptureError(ErrInvalidSignature)
return ErrInvalidSignature
@ -73,37 +71,14 @@ func (i RequestValidatorImpl) Validate(ctx context.Context, r *http.Request) err
}
func (i RequestValidatorImpl) ValidateFiberCtx(ctx context.Context, c *fiber.Ctx) error {
s := i.telemetry.StartSpan(ctx, "function", "validator/val_impls.RequestValidatorImpl.ValidateFiberCtx")
s := i.telemetry.StartSpan(ctx, "function", "val_impls/RequestValidatorImpl.ValidateFiberCtx")
defer s.End()
ctx = s.Context()
r, err := convertToStdRequest(c)
r, err := utils.ConvertToStdRequest(c)
if err != nil {
return err
}
return i.Validate(ctx, r)
}
func convertToStdRequest(c *fiber.Ctx) (*http.Request, error) {
stdReq := &http.Request{}
if err := fasthttpadaptor.ConvertRequest(c.Context(), stdReq, true); err != nil {
return nil, err
}
return stdReq, nil
}
func copyBody(req *http.Request) ([]byte, error) {
body, err := io.ReadAll(req.Body)
if err != nil {
return nil, err
}
if err := req.Body.Close(); err != nil {
return nil, err
}
req.Body = io.NopCloser(bytes.NewBuffer(body))
return body, nil
}

140
main.go
View file

@ -4,8 +4,11 @@ import (
"context"
"crypto/ed25519"
"crypto/rand"
"crypto/tls"
"database/sql"
"database/sql/driver"
"fmt"
"github.com/lysand-org/versia-go/ent/instancemetadata"
"github.com/lysand-org/versia-go/internal/handlers/follow_handler"
"github.com/lysand-org/versia-go/internal/handlers/meta_handler"
"github.com/lysand-org/versia-go/internal/handlers/note_handler"
@ -27,11 +30,9 @@ import (
"github.com/go-logr/zerologr"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/cors"
"github.com/google/uuid"
pgx "github.com/jackc/pgx/v5/stdlib"
"github.com/lysand-org/versia-go/config"
"github.com/lysand-org/versia-go/ent"
"github.com/lysand-org/versia-go/ent/user"
"github.com/lysand-org/versia-go/internal/database"
"github.com/lysand-org/versia-go/internal/handlers/user_handler"
"github.com/lysand-org/versia-go/internal/tasks"
@ -59,17 +60,23 @@ func main() {
tel, err := unitel.Initialize(config.C.Telemetry)
if err != nil {
log.Fatal().Err(err).Msg("failed to initialize telemetry")
log.Fatal().Err(err).Msg("Failed to initialize telemetry")
}
federationClient := lysand.NewClient(lysand.WithHTTPClient(&http.Client{
httpClient := &http.Client{
Transport: tel.NewTracedTransport(
http.DefaultTransport,
false,
[]string{"origin", "date", "signature"},
[]string{"host", "date", "signature"},
&http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: config.C.Telemetry.Environment == "development"}},
// TODO: Only forward traces to configured hosts
true,
[]string{"origin", "x-nonce", "x-signature", "x-signed-by", "sentry-trace", "sentry-baggage"},
[]string{"host", "x-nonce", "x-signature", "x-signed-by"},
),
}), lysand.WithLogger(zerologr.New(&log.Logger).WithName("federation-client")))
}
federationClient := lysand.NewClient(
lysand.WithHTTPClient(httpClient),
lysand.WithLogger(zerologr.New(&log.Logger).WithName("federation-client")),
)
log.Debug().Msg("Opening database connection")
var db *ent.Client
@ -79,37 +86,46 @@ func main() {
db, err = openDB(tel, true, config.C.DatabaseURI)
}
if err != nil {
log.Fatal().Err(err).Msg("failed opening connection to the database")
log.Fatal().Err(err).Msg("Failed opening connection to the database")
}
defer db.Close()
nc, err := nats.Connect(config.C.NATSURI)
if err != nil {
log.Fatal().Err(err).Msg("failed to connect to NATS")
log.Fatal().Err(err).Msg("Failed to connect to NATS")
}
log.Debug().Msg("Starting taskqueue client")
tq, err := taskqueue.NewClient(context.Background(), "versia-go", nc, tel, zerologr.New(&log.Logger).WithName("taskqueue-client"))
tq, err := taskqueue.NewClient(context.Background(), config.C.NATSStreamName, nc, tel, zerologr.New(&log.Logger).WithName("taskqueue-client"))
if err != nil {
log.Fatal().Err(err).Msg("failed to create taskqueue client")
log.Fatal().Err(err).Msg("Failed to create taskqueue client")
}
defer tq.Close()
log.Debug().Msg("Running schema migration")
if err := migrateDB(db, zerologr.New(&log.Logger).WithName("migrate-db"), tel); err != nil {
log.Fatal().Err(err).Msg("failed to run schema migration")
log.Fatal().Err(err).Msg("Failed to run schema migration")
}
// Stateless services
federationService := svc_impls.NewFederationServiceImpl(federationClient, tel, zerologr.New(&log.Logger).WithName("federation-service"))
requestSigner := svc_impls.NewRequestSignerImpl(tel, zerologr.New(&log.Logger).WithName("request-signer"))
federationService := svc_impls.NewFederationServiceImpl(httpClient, federationClient, tel, zerologr.New(&log.Logger).WithName("federation-service"))
taskService := svc_impls.NewTaskServiceImpl(tq, tel, zerologr.New(&log.Logger).WithName("task-service"))
// Manager
repos := repo_impls.NewManagerImpl(db, tel, zerologr.New(&log.Logger).WithName("repositories"), func(db *ent.Client, log logr.Logger, telemetry *unitel.Telemetry) repository.UserRepository {
return repo_impls.NewUserRepositoryImpl(federationService, db, log, telemetry)
}, repo_impls.NewNoteRepositoryImpl, repo_impls.NewFollowRepositoryImpl)
repos := repo_impls.NewManagerImpl(
db, tel, zerologr.New(&log.Logger).WithName("repositories"),
func(db *ent.Client, log logr.Logger, telemetry *unitel.Telemetry) repository.UserRepository {
return repo_impls.NewUserRepositoryImpl(federationService, db, log, telemetry)
},
repo_impls.NewNoteRepositoryImpl,
repo_impls.NewFollowRepositoryImpl,
func(db *ent.Client, log logr.Logger, telemetry *unitel.Telemetry) repository.InstanceMetadataRepository {
return repo_impls.NewInstanceMetadataRepositoryImpl(federationService, db, log, telemetry)
},
)
// Validators
@ -121,19 +137,20 @@ func main() {
userService := svc_impls.NewUserServiceImpl(repos, federationService, tel, zerologr.New(&log.Logger).WithName("user-service"))
noteService := svc_impls.NewNoteServiceImpl(federationService, taskService, repos, tel, zerologr.New(&log.Logger).WithName("note-service"))
followService := svc_impls.NewFollowServiceImpl(federationService, repos, tel, zerologr.New(&log.Logger).WithName("follow-service"))
inboxService := svc_impls.NewInboxService(repos, federationService, tel, zerologr.New(&log.Logger).WithName("inbox-service"))
inboxService := svc_impls.NewInboxService(federationService, repos, tel, zerologr.New(&log.Logger).WithName("inbox-service"))
instanceMetadataService := svc_impls.NewInstanceMetadataServiceImpl(federationService, repos, tel, zerologr.New(&log.Logger).WithName("instance-metadata-service"))
// Handlers
userHandler := user_handler.New(userService, federationService, inboxService, bodyValidator, requestValidator, zerologr.New(&log.Logger).WithName("user-handler"))
userHandler := user_handler.New(federationService, requestSigner, userService, inboxService, bodyValidator, requestValidator, zerologr.New(&log.Logger).WithName("user-handler"))
noteHandler := note_handler.New(noteService, bodyValidator, zerologr.New(&log.Logger).WithName("notes-handler"))
followHandler := follow_handler.New(followService, federationService, zerologr.New(&log.Logger).WithName("follow-handler"))
metaHandler := meta_handler.New(zerologr.New(&log.Logger).WithName("meta-handler"))
metaHandler := meta_handler.New(instanceMetadataService, zerologr.New(&log.Logger).WithName("meta-handler"))
// Initialization
if err := initServerActor(db, tel); err != nil {
log.Fatal().Err(err).Msg("failed to initialize server actor")
log.Fatal().Err(err).Msg("Failed to initialize server actor")
}
web := fiber.New(fiber.Config{
@ -160,9 +177,9 @@ func main() {
WaitForDelivery: false,
Timeout: 5 * time.Second,
// host for incoming requests
TraceRequestHeaders: []string{"origin", "date", "signature", "host"},
TraceRequestHeaders: []string{"origin", "x-nonce", "x-signature", "x-signed-by", "sentry-trace", "sentry-baggage"},
// origin for outgoing requests
TraceResponseHeaders: []string{"origin", "date", "signature", "origin"},
TraceResponseHeaders: []string{"host", "x-nonce", "x-signature", "x-signed-by"},
// IgnoredRoutes: nil,
}))
web.Use(unitel.RequestLogger(log.Logger, true, true))
@ -186,7 +203,7 @@ func main() {
tasks.NewHandler(federationService, repos, tel, zerologr.New(&log.Logger).WithName("task-handler")).
Register(tq)
if err := tq.Start(context.Background()); err != nil {
if err := tq.StartConsumer(context.Background(), "consumer"); err != nil {
log.Fatal().Err(err).Msg("failed to start taskqueue client")
}
}()
@ -195,7 +212,7 @@ func main() {
defer wg.Done()
log.Debug().Msg("Starting server")
if err := web.ListenTLS(":8443", "cert.pem", "key.pem"); err != nil {
if err := web.ListenTLS(fmt.Sprintf(":%d", config.C.Port), "cert.pem", "key.pem"); err != nil {
log.Fatal().Err(err).Msg("Failed to start server")
}
}()
@ -277,45 +294,44 @@ func initServerActor(db *ent.Client, telemetry *unitel.Telemetry) error {
}(tx)
ctx = tx.Context()
_, err = tx.User.Query().
Where(user.Username("actor")).
Only(ctx)
if err != nil && !ent.IsNotFound(err) {
log.Error().Err(err).Msg("Failed to query user")
pub, priv, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
log.Error().Err(err).Msg("Failed to generate keypair")
return err
}
if ent.IsNotFound(err) {
pub, priv, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
log.Error().Err(err).Msg("Failed to generate keypair")
return err
}
uid := uuid.New()
err = tx.User.Create().
SetID(uid).
SetUsername("actor").
SetIsRemote(false).
SetURI(utils.UserAPIURL(uid).String()).
SetIndexable(false).
SetPrivacyLevel(user.PrivacyLevelPrivate).
SetPublicKey(pub).
SetPrivateKey(priv).
SetInbox(utils.UserInboxAPIURL(uid).String()).
SetOutbox(utils.UserOutboxAPIURL(uid).String()).
SetFeatured(utils.UserFeaturedAPIURL(uid).String()).
SetFollowers(utils.UserFollowersAPIURL(uid).String()).
SetFollowing(utils.UserFollowingAPIURL(uid).String()).
Exec(ctx)
if err != nil {
log.Error().Err(err).Msg("Failed to create user")
return err
}
err = tx.InstanceMetadata.Create().
SetIsRemote(false).
SetURI(utils.InstanceMetadataAPIURL().String()).
SetName(config.C.InstanceName).
SetNillableDescription(config.C.InstanceDescription).
SetHost(config.C.Host).
SetPrivateKey(priv).
SetPublicKey(pub).
SetPublicKeyAlgorithm("ed25519").
SetSoftwareName("versia-go").
SetSoftwareVersion("0.0.1").
SetSharedInboxURI(utils.SharedInboxAPIURL().String()).
SetAdminsURI(utils.InstanceMetadataAdminsAPIURL().String()).
SetModeratorsURI(utils.InstanceMetadataModeratorsAPIURL().String()).
SetSupportedVersions([]string{"0.4.0"}).
SetSupportedExtensions([]string{}).
//
OnConflictColumns(instancemetadata.FieldHost).
UpdateName().
UpdateDescription().
UpdateHost().
UpdateSoftwareName().
UpdateSoftwareVersion().
UpdateSharedInboxURI().
UpdateAdminsURI().
UpdateModeratorsURI().
UpdateSupportedVersions().
UpdateSupportedExtensions().
Exec(ctx)
if err != nil {
log.Error().Err(err).Msg("Failed to create server metadata")
return err
}
tx.MarkForCommit()

View file

@ -1,15 +1,7 @@
package lysand
import (
"bytes"
"context"
"crypto/ed25519"
"crypto/rand"
"encoding/base64"
"encoding/json"
"fmt"
"net/http"
"net/url"
)
// User represents a user object in the Lysand protocol. For more information, see the [Spec].
@ -20,7 +12,7 @@ type User struct {
// PublicKey is the public key of the user.
// https://lysand.org/objects/user#public-key
PublicKey PublicKey `json:"public_key"`
PublicKey UserPublicKey `json:"public_key"`
// DisplayName is the display name of the user.
// https://lysand.org/objects/user#display-name
@ -66,14 +58,6 @@ type User struct {
// https://lysand.org/objects/user#following
Following *URL `json:"following"`
// Likes is the likes of the user.
// https://lysand.org/objects/user#likes
Likes *URL `json:"likes"`
// Dislikes is the dislikes of the user.
// https://lysand.org/objects/user#dislikes
Dislikes *URL `json:"dislikes"`
// Inbox is the inbox of the user.
// https://lysand.org/objects/user#posts
Inbox *URL `json:"inbox"`
@ -94,60 +78,3 @@ type Field struct {
Key TextContentTypeMap `json:"key"`
Value TextContentTypeMap `json:"value"`
}
func (c *FederationClient) GetUser(ctx context.Context, uri *url.URL) (*User, error) {
resp, body, err := c.rawGET(ctx, uri)
if err != nil {
return nil, err
}
user := &User{}
if err := json.Unmarshal(body, user); err != nil {
return nil, err
}
fedHeaders, err := ExtractFederationHeaders(resp.Header)
if err != nil {
return nil, err
}
v := Verifier{ed25519.PublicKey(user.PublicKey.PublicKey)}
if !v.Verify("GET", uri, body, fedHeaders) {
c.log.V(2).Info("signature verification failed", "user", user.URI.String())
return nil, fmt.Errorf("signature verification failed")
}
c.log.V(2).Info("signature verification succeeded", "user", user.URI.String())
return user, nil
}
func (c *FederationClient) SendToInbox(ctx context.Context, signer Signer, user *User, object any) ([]byte, error) {
uri := user.Inbox.ToStd()
body, err := json.Marshal(object)
if err != nil {
return nil, err
}
nonce := make([]byte, 32)
if _, err := rand.Read(nonce); err != nil {
return nil, err
}
sigData := NewSignatureData("POST", base64.StdEncoding.EncodeToString(nonce), uri, hashSHA256(body))
sig := signer.Sign(*sigData)
req, err := http.NewRequestWithContext(ctx, "POST", uri.String(), bytes.NewReader(body))
if err != nil {
return nil, err
}
sig.Inject(req.Header)
_, respBody, err := c.doReq(req)
if err != nil {
return nil, err
}
return respBody, nil
}

View file

@ -1,42 +1,5 @@
package lysand
import (
"bytes"
"crypto/ed25519"
"crypto/sha256"
"io"
"net/http"
)
func (c *FederationClient) ValidateSignatureHeader(req *http.Request) (bool, error) {
fedHeaders, err := ExtractFederationHeaders(req.Header)
if err != nil {
return false, err
}
// TODO: Fetch user from database instead of using the URI
user, err := c.GetUser(req.Context(), fedHeaders.SignedBy)
if err != nil {
return false, err
}
body, err := copyBody(req)
if err != nil {
return false, err
}
v := Verifier{ed25519.PublicKey(user.PublicKey.PublicKey)}
valid := v.Verify(req.Method, req.URL, body, fedHeaders)
return valid, nil
}
func hashSHA256(data []byte) []byte {
h := sha256.New()
h.Write(data)
return h.Sum(nil)
}
func must[In any, Out any](fn func(In) (Out, error), v In) Out {
out, err := fn(v)
if err != nil {
@ -45,17 +8,3 @@ func must[In any, Out any](fn func(In) (Out, error), v In) Out {
return out
}
func copyBody(req *http.Request) ([]byte, error) {
body, err := io.ReadAll(req.Body)
if err != nil {
return nil, err
}
if err := req.Body.Close(); err != nil {
return nil, err
}
req.Body = io.NopCloser(bytes.NewBuffer(body))
return body, nil
}

23
pkg/lysand/crypto/keys.go Normal file
View file

@ -0,0 +1,23 @@
package versiacrypto
import (
"crypto/ed25519"
"fmt"
)
type UnknownPublicKeyTypeError struct {
Got string
}
func (i UnknownPublicKeyTypeError) Error() string {
return fmt.Sprintf("unknown public key type: \"%s\"", i.Got)
}
func ToTypedKey(algorithm string, raw []byte) (any, error) {
switch algorithm {
case "ed25519":
return ed25519.PublicKey(raw), nil
default:
return nil, UnknownPublicKeyTypeError{algorithm}
}
}

View file

@ -0,0 +1,9 @@
package versiacrypto
import "crypto/sha256"
func SHA256(data []byte) []byte {
h := sha256.New()
h.Write(data)
return h.Sum(nil)
}

View file

@ -0,0 +1,29 @@
package versiacrypto
import (
"crypto"
"crypto/ed25519"
"fmt"
"reflect"
)
type InvalidPublicKeyTypeError struct {
Got reflect.Type
}
func (i InvalidPublicKeyTypeError) Error() string {
return fmt.Sprintf("failed to convert public key of type \"%s\"", i.Got.String())
}
type Verify = func(data, signature []byte) bool
func NewVerify(pubKey crypto.PublicKey) (Verify, error) {
switch pk := pubKey.(type) {
case ed25519.PublicKey:
return func(data, signature []byte) bool {
return ed25519.Verify(pk, data, signature)
}, nil
default:
return nil, InvalidPublicKeyTypeError{reflect.TypeOf(pk)}
}
}

View file

@ -1,10 +1,9 @@
package lysand
import (
"context"
"fmt"
"github.com/go-logr/logr"
"io"
"github.com/lysand-org/versia-go/pkg/protoretry"
"net/http"
"net/url"
"time"
@ -22,6 +21,7 @@ func (e *ResponseError) Error() string {
type FederationClient struct {
log logr.Logger
httpC *http.Client
hc *protoretry.Client
}
type Opt func(c *FederationClient)
@ -53,49 +53,11 @@ func NewClient(opts ...Opt) *FederationClient {
useragent: "github.com/lysand-org/versia-go/pkg/lysand#0.0.1",
}
c.hc = protoretry.New(c.httpC)
return c
}
func (c *FederationClient) rawGET(ctx context.Context, uri *url.URL) (*http.Response, []byte, error) {
req, err := http.NewRequestWithContext(ctx, "GET", uri.String(), nil)
if err != nil {
return nil, nil, err
}
return c.doReq(req)
}
func (c *FederationClient) rawPOST(ctx context.Context, uri *url.URL, body io.Reader) (*http.Response, []byte, error) {
req, err := http.NewRequestWithContext(ctx, "POST", uri.String(), body)
if err != nil {
return nil, nil, err
}
return c.doReq(req)
}
func (c *FederationClient) doReq(req *http.Request) (*http.Response, []byte, error) {
resp, err := c.httpC.Do(req)
if err != nil {
return nil, nil, err
}
defer resp.Body.Close()
if resp.StatusCode >= http.StatusBadRequest {
return resp, nil, &ResponseError{
StatusCode: resp.StatusCode,
URL: req.URL,
}
}
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return resp, nil, err
}
return resp, respBody, nil
}
type federationClientHTTPTransport struct {
inner http.RoundTripper
useragent string

View file

@ -25,6 +25,14 @@ func (f *FederationHeaders) Inject(h http.Header) {
h.Set("x-signature", base64.StdEncoding.EncodeToString(f.Signature))
}
func (f *FederationHeaders) Headers() map[string]string {
return map[string]string{
"x-signed-by": f.SignedBy.String(),
"x-nonce": f.Nonce,
"x-signature": base64.StdEncoding.EncodeToString(f.Signature),
}
}
func ExtractFederationHeaders(h http.Header) (*FederationHeaders, error) {
signedBy := h.Get("x-signed-by")
if signedBy == "" {
@ -41,14 +49,19 @@ func ExtractFederationHeaders(h http.Header) (*FederationHeaders, error) {
return nil, fmt.Errorf("missing x-nonce header")
}
signature := h.Get("x-signature")
if signature == "" {
rawSignature := h.Get("x-signature")
if rawSignature == "" {
return nil, fmt.Errorf("missing x-signature header")
}
signature, err := base64.StdEncoding.DecodeString(rawSignature)
if err != nil {
return nil, err
}
return &FederationHeaders{
SignedBy: u,
Nonce: nonce,
Signature: []byte(signature),
Signature: signature,
}, nil
}

View file

@ -0,0 +1,111 @@
package lysand
import (
"encoding/json"
)
// InstanceMetadata represents the metadata of a Lysand instance. For more information, see the [Spec].
//
// ! Unlike other entities, instance metadata is not meant to be federated.
//
// [Spec]: https://versia.pub/entities/instance-metadata
type InstanceMetadata struct {
// Type is always "InstanceMetadata"
Type string `json:"type"`
// Extensions is a map of active extensions
Extensions Extensions `json:"extensions,omitempty"`
// Name is the name of the instance
Name string `json:"name"`
// Description is a description of the instance
Description *string `json:"description,omitempty"`
// Host is the hostname of the instance, including the port
Host string `json:"host,omitempty"`
// PublicKey is the public key of the instance
PublicKey InstancePublicKey `json:"public_key"`
// SharedInbox is the URL to the instance's shared inbox
SharedInbox *URL `json:"shared_inbox,omitempty"`
// Moderators is a URL to a collection of moderators
Moderators *URL `json:"moderators,omitempty"`
// Admins is a URL to a collection of administrators
Admins *URL `json:"admins,omitempty"`
// Logo is the URL to the instance's logo
Logo *ImageContentTypeMap `json:"logo,omitempty"`
// Banner is the URL to the instance's banner
Banner *ImageContentTypeMap `json:"banner,omitempty"`
// Software is information about the instance software
Software InstanceSoftware `json:"software"`
// Compatibility is information about the instance's compatibility with different Lysand versions
Compatibility InstanceCompatibility `json:"compatibility"`
}
func (s InstanceMetadata) MarshalJSON() ([]byte, error) {
type instanceMetadata InstanceMetadata
s2 := instanceMetadata(s)
s2.Type = "InstanceMetadata"
return json.Marshal(s2)
}
// InstanceSoftware represents the software of a Lysand instance.
type InstanceSoftware struct {
// Name is the name of the instance software
Name string `json:"name"`
// Version is the version of the instance software
Version string `json:"version"`
}
// InstanceCompatibility represents the compatibility of a Lysand instance.
type InstanceCompatibility struct {
// Versions is a list of versions of Lysand the instance is compatible with
Versions []string `json:"versions"`
// Extensions is a list of extensions supported by the instance
Extensions []string `json:"extensions"`
}
// InstancePublicKey represents the public key of a Versia instance.
type InstancePublicKey struct {
// Algorithm can only be `ed25519` for now
Algorithm string `json:"algorithm"`
Key *SPKIPublicKey `json:"-"`
RawKey json.RawMessage `json:"key"`
}
func (k *InstancePublicKey) UnmarshalJSON(raw []byte) error {
type t InstancePublicKey
k2 := (*t)(k)
if err := json.Unmarshal(raw, k2); err != nil {
return nil
}
var err error
if k2.Key, err = unmarshalSPKIPubKey(k2.Algorithm, k2.RawKey); err != nil {
return nil
}
return nil
}
func (k InstancePublicKey) MarshalJSON() ([]byte, error) {
type t InstancePublicKey
k2 := t(k)
var err error
if k2.RawKey, err = k2.Key.MarshalJSON(); err != nil {
return nil, err
}
return json.Marshal(k2)
}

View file

@ -1,64 +0,0 @@
package lysand
import (
"encoding/json"
"github.com/Masterminds/semver"
)
// ServerMetadata represents the metadata of a Lysand server. For more information, see the [Spec].
//
// ! Unlike other objects, server metadata is not meant to be federated.
//
// [Spec]: https://lysand.org/objects/server-metadata
type ServerMetadata struct {
// Type is always "ServerMetadata"
// https://lysand.org/objects/server-metadata#type
Type string `json:"type"`
// Extensions is a map of active extensions
// https://lysand.org/objects/server-metadata#extensions
Extensions Extensions `json:"extensions,omitempty"`
// Name is the name of the server
// https://lysand.org/objects/server-metadata#name
Name string `json:"name"`
// Version is the version of the server software
// https://lysand.org/objects/server-metadata#version
Version *semver.Version `json:"version"`
// Description is a description of the server
// https://lysand.org/objects/server-metadata#description
Description *string `json:"description,omitempty"`
// Website is the URL to the server's website
// https://lysand.org/objects/server-metadata#website
Website *URL `json:"website,omitempty"`
// Moderators is a list of URLs to moderators
// https://lysand.org/objects/server-metadata#moderators
Moderators []*URL `json:"moderators,omitempty"`
// Admins is a list of URLs to administrators
// https://lysand.org/objects/server-metadata#admins
Admins []*URL `json:"admins,omitempty"`
// Logo is the URL to the server's logo
// https://lysand.org/objects/server-metadata#logo
Logo *ImageContentTypeMap `json:"logo,omitempty"`
// Banner is the URL to the server's banner
// https://lysand.org/objects/server-metadata#banner
Banner *ImageContentTypeMap `json:"banner,omitempty"`
// SupportedExtensions is a list of supported extensions
SupportedExtensions []string `json:"supported_extensions"`
}
func (s ServerMetadata) MarshalJSON() ([]byte, error) {
type serverMetadata ServerMetadata
s2 := serverMetadata(s)
s2.Type = "ServerMetadata"
return json.Marshal(s2)
}

View file

@ -1,10 +1,13 @@
package lysand
import (
"crypto"
"crypto/ed25519"
"encoding/base64"
"fmt"
versiacrypto "github.com/lysand-org/versia-go/pkg/lysand/crypto"
"net/url"
"os"
"strings"
)
@ -32,8 +35,16 @@ func (s *SignatureData) String() string {
return fmt.Sprintf("%s %s?%s %s %s", strings.ToLower(s.RequestMethod), s.URL.Path, s.URL.RawQuery, s.Nonce, base64.StdEncoding.EncodeToString(s.Digest))
}
func (s *SignatureData) Validate(pubKey ed25519.PublicKey, signature []byte) bool {
return ed25519.Verify(pubKey, []byte(s.String()), signature)
func (s *SignatureData) Validate(pubKey crypto.PublicKey, signature []byte) bool {
data := []byte(s.String())
verify, err := versiacrypto.NewVerify(pubKey)
if err != nil {
_, _ = fmt.Fprintf(os.Stderr, "%v\n", err)
return false
}
return verify(data, signature)
}
func (s *SignatureData) Sign(privKey ed25519.PrivateKey) []byte {
@ -54,11 +65,10 @@ func (s Signer) Sign(signatureData SignatureData) *FederationHeaders {
}
type Verifier struct {
PublicKey ed25519.PublicKey
PublicKey crypto.PublicKey
}
func (v Verifier) Verify(method string, u *url.URL, body []byte, fedHeaders *FederationHeaders) bool {
sigData := NewSignatureData(method, fedHeaders.Nonce, u, hashSHA256(body))
return sigData.Validate(v.PublicKey, fedHeaders.Signature)
return NewSignatureData(method, fedHeaders.Nonce, u, versiacrypto.SHA256(body)).
Validate(v.PublicKey, fedHeaders.Signature)
}

View file

@ -1,59 +1,92 @@
package lysand
import (
"crypto/ed25519"
"crypto"
"crypto/x509"
"encoding/base64"
"encoding/json"
"errors"
)
var (
ErrInvalidPublicKeyType = errors.New("invalid public key type")
)
// PublicKey represents a public key for a user. For more information, see the [Spec].
// UserPublicKey represents a public key for a user. For more information, see the [Spec].
//
// [Spec]: https://lysand.org/security/keys#public-key-cryptography
type PublicKey struct {
PublicKey SPKIPublicKey `json:"public_key"`
Actor *URL `json:"actor"`
type UserPublicKey struct {
Actor *URL `json:"actor"`
// Algorithm can only be `ed25519` for now
Algorithm string `json:"algorithm"`
Key *SPKIPublicKey `json:"-"`
RawKey json.RawMessage `json:"key"`
}
// SPKIPublicKey is a type that represents a [ed25519.PublicKey] in the SPKI
// format.
type SPKIPublicKey ed25519.PublicKey
func (k *UserPublicKey) UnmarshalJSON(raw []byte) error {
type t UserPublicKey
k2 := (*t)(k)
// UnmarshalJSON decodes the public key from a base64 encoded string and then unmarshals it from the SPKI form.
func (k *SPKIPublicKey) UnmarshalJSON(raw []byte) error {
rawStr := ""
if err := json.Unmarshal(raw, &rawStr); err != nil {
if err := json.Unmarshal(raw, k2); err != nil {
return err
}
raw, err := base64.StdEncoding.DecodeString(rawStr)
if err != nil {
var err error
if k2.Key, err = unmarshalSPKIPubKey(k2.Algorithm, k2.RawKey); err != nil {
return err
}
parsed, err := x509.ParsePKIXPublicKey(raw)
if err != nil {
return err
}
edKey, ok := parsed.(ed25519.PublicKey)
if !ok {
return ErrInvalidPublicKeyType
}
*k = SPKIPublicKey(edKey)
*k = UserPublicKey(*k2)
return nil
}
func (k UserPublicKey) MarshalJSON() ([]byte, error) {
type t UserPublicKey
k2 := t(k)
var err error
if k2.RawKey, err = k2.Key.MarshalJSON(); err != nil {
return nil, err
}
return json.Marshal(k2)
}
// SPKIPublicKey is a type that represents a [ed25519.PublicKey] in the SPKI
// format.
type SPKIPublicKey struct {
Key any
Algorithm string
}
func unmarshalSPKIPubKey(algorithm string, raw []byte) (*SPKIPublicKey, error) {
rawStr := ""
if err := json.Unmarshal(raw, &rawStr); err != nil {
return nil, err
}
raw, err := base64.StdEncoding.DecodeString(rawStr)
if err != nil {
return nil, err
}
return NewSPKIPubKey(algorithm, raw)
}
// NewSPKIPubKey decodes the public key from a base64 encoded string and then unmarshals it from the SPKI form.
func NewSPKIPubKey(algorithm string, raw []byte) (*SPKIPublicKey, error) {
parsed, err := x509.ParsePKIXPublicKey(raw)
if err != nil {
return nil, err
}
return &SPKIPublicKey{
Key: parsed,
Algorithm: algorithm,
}, nil
}
// MarshalJSON marshals the SPKI-encoded public key to a base64 encoded string.
func (k SPKIPublicKey) MarshalJSON() ([]byte, error) {
raw, err := x509.MarshalPKIXPublicKey(ed25519.PublicKey(k))
raw, err := x509.MarshalPKIXPublicKey(k.Key)
if err != nil {
return nil, err
}
@ -61,6 +94,6 @@ func (k SPKIPublicKey) MarshalJSON() ([]byte, error) {
return json.Marshal(base64.StdEncoding.EncodeToString(raw))
}
func (k SPKIPublicKey) ToStd() ed25519.PublicKey {
return ed25519.PublicKey(k)
func (k SPKIPublicKey) ToKey() crypto.PublicKey {
return k.Key
}

View file

@ -12,20 +12,20 @@ import (
func TestSPKIPublicKey_UnmarshalJSON(t *testing.T) {
expectedPk := must(x509.ParsePKIXPublicKey, must(base64.StdEncoding.DecodeString, "MCowBQYDK2VwAyEAgKNt+9eyOXdb7MSrrmHlsFD2H9NGwC+56PjpWD46Tcs="))
pk := PublicKey{}
pk := UserPublicKey{}
raw := []byte(`{"public_key":"MCowBQYDK2VwAyEAgKNt+9eyOXdb7MSrrmHlsFD2H9NGwC+56PjpWD46Tcs="}`)
if err := json.Unmarshal(raw, &pk); err != nil {
t.Error(err)
}
assert.Equal(t, expectedPk, ed25519.PublicKey(pk.PublicKey))
assert.Equal(t, expectedPk, ed25519.PublicKey(pk.Key))
}
func TestSPKIPublicKey_MarshalJSON(t *testing.T) {
expectedPk := must(x509.ParsePKIXPublicKey, must(base64.StdEncoding.DecodeString, "MCowBQYDK2VwAyEAgKNt+9eyOXdb7MSrrmHlsFD2H9NGwC+56PjpWD46Tcs=")).(ed25519.PublicKey)
pk := PublicKey{
PublicKey: SPKIPublicKey(expectedPk),
pk := UserPublicKey{
Key: SPKIPublicKey(expectedPk),
}
if _, err := json.Marshal(pk); err != nil {
t.Error(err)

62
pkg/protoretry/client.go Normal file
View file

@ -0,0 +1,62 @@
package protoretry
import (
"context"
"errors"
"io"
"net/http"
"net/url"
"syscall"
)
type Client struct {
base *http.Client
}
func New(base *http.Client) *Client {
return &Client{base}
}
func (c *Client) Do(req *http.Request) (*http.Response, error) {
if res, err := c.base.Do(req); err == nil {
return res, nil
} else if !errors.Is(err, syscall.ECONNREFUSED) {
return nil, err
}
req.URL.Scheme = "http"
return c.base.Do(req)
}
func (c *Client) GET(ctx context.Context, u *url.URL) ([]byte, *http.Response, error) {
req, err := http.NewRequestWithContext(ctx, "GET", u.String(), nil)
if err != nil {
return nil, nil, err
}
return c.DoReq(req)
}
func (c *Client) POST(ctx context.Context, u *url.URL, reqBody io.Reader) ([]byte, *http.Response, error) {
req, err := http.NewRequestWithContext(ctx, "POST", u.String(), reqBody)
if err != nil {
return nil, nil, err
}
return c.DoReq(req)
}
func (c *Client) DoReq(req *http.Request) ([]byte, *http.Response, error) {
res, err := c.Do(req)
if err != nil {
return nil, nil, err
}
defer res.Body.Close()
resBody, err := io.ReadAll(res.Body)
if err != nil {
return nil, nil, err
}
return resBody, res, nil
}

View file

@ -71,15 +71,15 @@ type Client struct {
log logr.Logger
}
func NewClient(ctx context.Context, name string, natsClient *nats.Conn, telemetry *unitel.Telemetry, log logr.Logger) (*Client, error) {
func NewClient(ctx context.Context, streamName string, natsClient *nats.Conn, telemetry *unitel.Telemetry, log logr.Logger) (*Client, error) {
js, err := jetstream.New(natsClient)
if err != nil {
return nil, err
}
s, err := js.CreateStream(ctx, jetstream.StreamConfig{
Name: name,
Subjects: []string{name + ".*"},
Name: streamName,
Subjects: []string{streamName + ".*"},
MaxConsumers: -1,
MaxMsgs: -1,
Discard: jetstream.DiscardOld,
@ -89,7 +89,7 @@ func NewClient(ctx context.Context, name string, natsClient *nats.Conn, telemetr
AllowDirect: true,
})
if errors.Is(err, nats.ErrStreamNameAlreadyInUse) {
s, err = js.Stream(ctx, name)
s, err = js.Stream(ctx, streamName)
if err != nil {
return nil, err
}
@ -100,8 +100,8 @@ func NewClient(ctx context.Context, name string, natsClient *nats.Conn, telemetr
stopCh := make(chan struct{})
c := &Client{
name: name,
subject: name + ".tasks",
name: streamName,
subject: streamName + ".tasks",
handlers: map[string][]Handler{},
@ -145,7 +145,7 @@ func (c *Client) Submit(ctx context.Context, task Task) error {
if err != nil {
return err
}
c.log.V(1).Info("submitted task", "id", task.ID, "type", task.Type, "sequence", msg.Sequence)
c.log.V(2).Info("Submitted task", "id", task.ID, "type", task.Type, "sequence", msg.Sequence)
s.AddAttribute("messaging.message.id", msg.Sequence)
@ -153,7 +153,7 @@ func (c *Client) Submit(ctx context.Context, task Task) error {
}
func (c *Client) RegisterHandler(type_ string, handler Handler) {
c.log.V(2).Info("registering handler", "type", type_)
c.log.V(2).Info("Registering handler", "type", type_)
if _, ok := c.handlers[type_]; !ok {
c.handlers[type_] = []Handler{}
@ -161,13 +161,11 @@ func (c *Client) RegisterHandler(type_ string, handler Handler) {
c.handlers[type_] = append(c.handlers[type_], handler)
}
func (c *Client) Start(ctx context.Context) error {
c.log.Info("starting")
func (c *Client) StartConsumer(ctx context.Context, consumerGroup string) error {
c.log.Info("Starting consumer")
sub, err := c.js.CreateConsumer(ctx, c.name, jetstream.ConsumerConfig{
// TODO: set name properly
Name: "versia-go",
Durable: "versia-go",
Durable: consumerGroup,
DeliverPolicy: jetstream.DeliverAllPolicy,
ReplayPolicy: jetstream.ReplayInstantPolicy,
AckPolicy: jetstream.AckExplicitPolicy,
@ -191,16 +189,16 @@ func (c *Client) Start(ctx context.Context) error {
msg, err := m.Next()
if err != nil {
if errors.Is(err, jetstream.ErrMsgIteratorClosed) {
c.log.Info("stopping")
c.log.Info("Stopping")
return
}
c.log.Error(err, "failed to get next message")
c.log.Error(err, "Failed to get next message")
break
}
if err := c.handleTask(ctx, msg); err != nil {
c.log.Error(err, "failed to handle task")
c.log.Error(err, "Failed to handle task")
break
}
}
@ -224,7 +222,7 @@ func (c *Client) handleTask(ctx context.Context, msg jetstream.Msg) error {
var w taskWrapper
if err := json.Unmarshal(data, &w); err != nil {
if err := msg.Nak(); err != nil {
c.log.Error(err, "failed to nak message")
c.log.Error(err, "Failed to nak message")
}
return err
@ -246,21 +244,21 @@ func (c *Client) handleTask(ctx context.Context, msg jetstream.Msg) error {
handlers, ok := c.handlers[w.Task.Type]
if !ok {
c.log.V(1).Info("no handler for task", "type", w.Task.Type)
c.log.V(2).Info("No handler for task", "type", w.Task.Type)
return msg.Nak()
}
var errs CombinedError
for _, handler := range handlers {
if err := handler(ctx, w.Task); err != nil {
c.log.Error(err, "handler failed", "type", w.Task.Type)
c.log.Error(err, "Handler failed", "type", w.Task.Type)
errs.Errors = append(errs.Errors, err)
}
}
if len(errs.Errors) > 0 {
if err := msg.Nak(); err != nil {
c.log.Error(err, "failed to nak message")
c.log.Error(err, "Failed to nak message")
errs.Errors = append(errs.Errors, err)
}

View file

@ -1,13 +1,19 @@
package webfinger
import (
"context"
"encoding/json"
"errors"
"fmt"
"github.com/lysand-org/versia-go/pkg/protoretry"
"net/http"
"net/url"
"strings"
)
var (
ErrInvalidSyntax = errors.New("must follow the format \"acct:<ID|Username>@<DOMAIN>\"")
ErrUserNotFound = errors.New("user could not be found")
)
func ParseResource(res string) (*UserID, error) {
@ -48,7 +54,7 @@ type Response struct {
type Link struct {
Relation string `json:"rel"`
Type any `json:"type"`
Type string `json:"type"`
Link string `json:"href"`
}
@ -70,3 +76,47 @@ func (u User) WebFingerResource() Response {
},
}
}
func Discover(c *protoretry.Client, ctx context.Context, baseURI, username string) (*User, error) {
u := &User{UserID: UserID{ID: username, Domain: baseURI}}
body, resp, err := c.GET(ctx, &url.URL{
Scheme: "https",
Host: u.UserID.Domain,
Path: "/.well-known/webfinger",
RawQuery: url.Values{"resource": []string{"acct:" + u.String()}}.Encode(),
})
if err != nil {
return nil, err
}
if resp.StatusCode == http.StatusNotFound {
return nil, ErrUserNotFound
} else if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
}
var respBody Response
if err := json.Unmarshal(body, &respBody); err != nil {
return nil, err
}
if respBody.Error != nil {
return nil, fmt.Errorf("webfinger error: %s", *respBody.Error)
}
for _, link := range respBody.Links {
if link.Relation == "self" {
if u.URI, err = url.Parse(link.Link); err != nil {
return nil, err
}
} else if link.Relation == "avatar" {
u.AvatarMIMEType = link.Type
if u.Avatar, err = url.Parse(link.Link); err != nil {
return nil, err
}
}
}
return u, nil
}