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" PORT=8443
INSTANCE_NAME="lysand-test"
INSTANCE_DESCRIPTION="Versia-Go Instance"
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 # SQLite
DATABASE_URI="file:./versia-go.db?cache=shared&_fk=1" DATABASE_URI=file:./versia-go.db?cache=shared&_fk=1
# PostgreSQL # PostgreSQL
# DATABASE_URI="postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable" # DATABASE_URI=postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable
ENVIRONMENT="development" ENVIRONMENT=development
OTLP_ENDPOINT="" OTLP_ENDPOINT=
SENTRY_DSN="" SENTRY_DSN=

5
.gitignore vendored
View file

@ -1,4 +1,5 @@
cert.pem *.pem
key.pem *.crt
*.db *.db
.env.* .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: services:
db: # db:
image: postgres:16.2-alpine # image: postgres:16.2-alpine
environment: # environment:
POSTGRES_DB: postgres # POSTGRES_DB: postgres
POSTGRES_USER: postgres # POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres # POSTGRES_PASSWORD: postgres
ports: # ports:
- "5432:5432" # - "5432:5432"
nats: nats:
image: nats:2.9.25-scratch image: nats:2.9.25-scratch
@ -14,3 +20,49 @@ services:
- "4222:4222" - "4222:4222"
- "8222:8222" - "8222:8222"
command: "--js" 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 ( import (
"net/url" "net/url"
"os" "os"
"strconv"
"git.devminer.xyz/devminer/unitel" "git.devminer.xyz/devminer/unitel"
"github.com/joho/godotenv" "github.com/joho/godotenv"
@ -10,11 +11,18 @@ import (
) )
type Config struct { type Config struct {
Port int
PublicAddress *url.URL PublicAddress *url.URL
Host string
SharedInboxURL *url.URL
InstanceName string InstanceName string
InstanceDescription *string InstanceDescription *string
NATSURI string NATSURI string
NATSStreamName string
DatabaseURI string DatabaseURI string
Telemetry unitel.Opts Telemetry unitel.Opts
@ -33,11 +41,17 @@ func Load() {
} }
C = Config{ C = Config{
Port: getEnvInt("PORT", 80),
PublicAddress: publicAddress, PublicAddress: publicAddress,
Host: publicAddress.Host,
SharedInboxURL: publicAddress.ResolveReference(&url.URL{Path: "/api/inbox"}),
InstanceName: os.Getenv("INSTANCE_NAME"), InstanceName: os.Getenv("INSTANCE_NAME"),
InstanceDescription: optionalEnvStr("INSTANCE_DESCRIPTION"), InstanceDescription: optionalEnvStr("INSTANCE_DESCRIPTION"),
NATSURI: os.Getenv("NATS_URI"), NATSURI: os.Getenv("NATS_URI"),
NATSStreamName: getEnvStr("NATS_STREAM_NAME", "versia-go"),
DatabaseURI: os.Getenv("DATABASE_URI"), DatabaseURI: os.Getenv("DATABASE_URI"),
Telemetry: unitel.ParseOpts("versia-go"), Telemetry: unitel.ParseOpts("versia-go"),
@ -53,3 +67,24 @@ func optionalEnvStr(key string) *string {
} }
return &value 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/attachment"
"github.com/lysand-org/versia-go/ent/follow" "github.com/lysand-org/versia-go/ent/follow"
"github.com/lysand-org/versia-go/ent/image" "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/note"
"github.com/lysand-org/versia-go/ent/servermetadata"
"github.com/lysand-org/versia-go/ent/user" "github.com/lysand-org/versia-go/ent/user"
) )
@ -35,10 +35,10 @@ type Client struct {
Follow *FollowClient Follow *FollowClient
// Image is the client for interacting with the Image builders. // Image is the client for interacting with the Image builders.
Image *ImageClient 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 is the client for interacting with the Note builders.
Note *NoteClient 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 is the client for interacting with the User builders.
User *UserClient User *UserClient
} }
@ -55,8 +55,8 @@ func (c *Client) init() {
c.Attachment = NewAttachmentClient(c.config) c.Attachment = NewAttachmentClient(c.config)
c.Follow = NewFollowClient(c.config) c.Follow = NewFollowClient(c.config)
c.Image = NewImageClient(c.config) c.Image = NewImageClient(c.config)
c.InstanceMetadata = NewInstanceMetadataClient(c.config)
c.Note = NewNoteClient(c.config) c.Note = NewNoteClient(c.config)
c.ServerMetadata = NewServerMetadataClient(c.config)
c.User = NewUserClient(c.config) c.User = NewUserClient(c.config)
} }
@ -153,8 +153,8 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) {
Attachment: NewAttachmentClient(cfg), Attachment: NewAttachmentClient(cfg),
Follow: NewFollowClient(cfg), Follow: NewFollowClient(cfg),
Image: NewImageClient(cfg), Image: NewImageClient(cfg),
InstanceMetadata: NewInstanceMetadataClient(cfg),
Note: NewNoteClient(cfg), Note: NewNoteClient(cfg),
ServerMetadata: NewServerMetadataClient(cfg),
User: NewUserClient(cfg), User: NewUserClient(cfg),
}, nil }, nil
} }
@ -178,8 +178,8 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error)
Attachment: NewAttachmentClient(cfg), Attachment: NewAttachmentClient(cfg),
Follow: NewFollowClient(cfg), Follow: NewFollowClient(cfg),
Image: NewImageClient(cfg), Image: NewImageClient(cfg),
InstanceMetadata: NewInstanceMetadataClient(cfg),
Note: NewNoteClient(cfg), Note: NewNoteClient(cfg),
ServerMetadata: NewServerMetadataClient(cfg),
User: NewUserClient(cfg), User: NewUserClient(cfg),
}, nil }, nil
} }
@ -210,7 +210,7 @@ func (c *Client) Close() error {
// In order to add hooks to a specific client, call: `client.Node.Use(...)`. // In order to add hooks to a specific client, call: `client.Node.Use(...)`.
func (c *Client) Use(hooks ...Hook) { func (c *Client) Use(hooks ...Hook) {
for _, n := range []interface{ Use(...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...) 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(...)`. // In order to add interceptors to a specific client, call: `client.Node.Intercept(...)`.
func (c *Client) Intercept(interceptors ...Interceptor) { func (c *Client) Intercept(interceptors ...Interceptor) {
for _, n := range []interface{ Intercept(...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...) n.Intercept(interceptors...)
} }
@ -235,10 +235,10 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) {
return c.Follow.mutate(ctx, m) return c.Follow.mutate(ctx, m)
case *ImageMutation: case *ImageMutation:
return c.Image.mutate(ctx, m) return c.Image.mutate(ctx, m)
case *InstanceMetadataMutation:
return c.InstanceMetadata.mutate(ctx, m)
case *NoteMutation: case *NoteMutation:
return c.Note.mutate(ctx, m) return c.Note.mutate(ctx, m)
case *ServerMetadataMutation:
return c.ServerMetadata.mutate(ctx, m)
case *UserMutation: case *UserMutation:
return c.User.mutate(ctx, m) return c.User.mutate(ctx, m)
default: 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. // NoteClient is a client for the Note schema.
type NoteClient struct { type NoteClient struct {
config 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. // UserClient is a client for the User schema.
type UserClient struct { type UserClient struct {
config config
@ -1211,6 +1227,54 @@ func (c *UserClient) QueryMentionedNotes(u *User) *NoteQuery {
return query 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. // Hooks returns the client hooks.
func (c *UserClient) Hooks() []Hook { func (c *UserClient) Hooks() []Hook {
return c.hooks.User 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. // hooks and interceptors per client, for fast access.
type ( type (
hooks struct { hooks struct {
Attachment, Follow, Image, Note, ServerMetadata, User []ent.Hook Attachment, Follow, Image, InstanceMetadata, Note, User []ent.Hook
} }
inters struct { 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/attachment"
"github.com/lysand-org/versia-go/ent/follow" "github.com/lysand-org/versia-go/ent/follow"
"github.com/lysand-org/versia-go/ent/image" "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/note"
"github.com/lysand-org/versia-go/ent/servermetadata"
"github.com/lysand-org/versia-go/ent/user" "github.com/lysand-org/versia-go/ent/user"
) )
@ -81,8 +81,8 @@ func checkColumn(table, column string) error {
attachment.Table: attachment.ValidColumn, attachment.Table: attachment.ValidColumn,
follow.Table: follow.ValidColumn, follow.Table: follow.ValidColumn,
image.Table: image.ValidColumn, image.Table: image.ValidColumn,
instancemetadata.Table: instancemetadata.ValidColumn,
note.Table: note.ValidColumn, note.Table: note.ValidColumn,
servermetadata.Table: servermetadata.ValidColumn,
user.Table: user.ValidColumn, user.Table: user.ValidColumn,
}) })
}) })

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) 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 // The NoteFunc type is an adapter to allow the use of ordinary
// function as Note mutator. // function as Note mutator.
type NoteFunc func(context.Context, *ent.NoteMutation) (ent.Value, error) 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) 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 // The UserFunc type is an adapter to allow the use of ordinary
// function as User mutator. // function as User mutator.
type UserFunc func(context.Context, *ent.UserMutation) (ent.Value, error) type UserFunc func(context.Context, *ent.UserMutation) (ent.Value, error)

View file

@ -36,6 +36,11 @@ func ValidColumn(column string) bool {
return false 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. // OrderOption defines the ordering options for the Image queries.
type OrderOption func(*sql.Selector) type OrderOption func(*sql.Selector)

View file

@ -70,6 +70,11 @@ func (ic *ImageCreate) check() error {
if _, ok := ic.mutation.URL(); !ok { if _, ok := ic.mutation.URL(); !ok {
return &ValidationError{Name: "url", err: errors.New(`ent: missing required field "Image.url"`)} 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 { if _, ok := ic.mutation.MimeType(); !ok {
return &ValidationError{Name: "mimeType", err: errors.New(`ent: missing required field "Image.mimeType"`)} 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) { 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)) _spec := sqlgraph.NewUpdateSpec(image.Table, image.Columns, sqlgraph.NewFieldSpec(image.FieldID, field.TypeInt))
if ps := iu.mutation.predicates; len(ps) > 0 { if ps := iu.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) { _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) { 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)) _spec := sqlgraph.NewUpdateSpec(image.Table, image.Columns, sqlgraph.NewFieldSpec(image.FieldID, field.TypeInt))
id, ok := iuo.mutation.ID() id, ok := iuo.mutation.ID()
if !ok { 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, Columns: ImagesColumns,
PrimaryKey: []*schema.Column{ImagesColumns[0]}, 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 holds the columns for the "notes" table.
NotesColumns = []*schema.Column{ NotesColumns = []*schema.Column{
{Name: "id", Type: field.TypeUUID}, {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 holds the columns for the "users" table.
UsersColumns = []*schema.Column{ UsersColumns = []*schema.Column{
{Name: "id", Type: field.TypeUUID}, {Name: "id", Type: field.TypeUUID},
@ -181,6 +171,8 @@ var (
{Name: "display_name", Type: field.TypeString, Nullable: true, Size: 256}, {Name: "display_name", Type: field.TypeString, Nullable: true, Size: 256},
{Name: "biography", Type: field.TypeString, Nullable: true}, {Name: "biography", Type: field.TypeString, Nullable: true},
{Name: "public_key", Type: field.TypeBytes}, {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: "private_key", Type: field.TypeBytes, Nullable: true},
{Name: "indexable", Type: field.TypeBool, Default: true}, {Name: "indexable", Type: field.TypeBool, Default: true},
{Name: "privacy_level", Type: field.TypeEnum, Enums: []string{"public", "restricted", "private"}, Default: "public"}, {Name: "privacy_level", Type: field.TypeEnum, Enums: []string{"public", "restricted", "private"}, Default: "public"},
@ -201,18 +193,93 @@ var (
ForeignKeys: []*schema.ForeignKey{ ForeignKeys: []*schema.ForeignKey{
{ {
Symbol: "users_images_avatarImage", Symbol: "users_images_avatarImage",
Columns: []*schema.Column{UsersColumns[20]}, Columns: []*schema.Column{UsersColumns[22]},
RefColumns: []*schema.Column{ImagesColumns[0]}, RefColumns: []*schema.Column{ImagesColumns[0]},
OnDelete: schema.SetNull, OnDelete: schema.SetNull,
}, },
{ {
Symbol: "users_images_headerImage", Symbol: "users_images_headerImage",
Columns: []*schema.Column{UsersColumns[21]}, Columns: []*schema.Column{UsersColumns[23]},
RefColumns: []*schema.Column{ImagesColumns[0]}, RefColumns: []*schema.Column{ImagesColumns[0]},
OnDelete: schema.SetNull, 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 holds the columns for the "note_mentions" table.
NoteMentionsColumns = []*schema.Column{ NoteMentionsColumns = []*schema.Column{
{Name: "note_id", Type: field.TypeUUID}, {Name: "note_id", Type: field.TypeUUID},
@ -243,9 +310,12 @@ var (
AttachmentsTable, AttachmentsTable,
FollowsTable, FollowsTable,
ImagesTable, ImagesTable,
InstanceMetadataTable,
NotesTable, NotesTable,
ServerMetadataTable,
UsersTable, UsersTable,
InstanceMetadataUsersTable,
InstanceMetadataModeratorsTable,
InstanceMetadataAdminsTable,
NoteMentionsTable, NoteMentionsTable,
} }
) )
@ -256,10 +326,14 @@ func init() {
FollowsTable.ForeignKeys[0].RefTable = UsersTable FollowsTable.ForeignKeys[0].RefTable = UsersTable
FollowsTable.ForeignKeys[1].RefTable = UsersTable FollowsTable.ForeignKeys[1].RefTable = UsersTable
NotesTable.ForeignKeys[0].RefTable = UsersTable NotesTable.ForeignKeys[0].RefTable = UsersTable
ServerMetadataTable.ForeignKeys[0].RefTable = UsersTable
ServerMetadataTable.ForeignKeys[1].RefTable = UsersTable
UsersTable.ForeignKeys[0].RefTable = ImagesTable UsersTable.ForeignKeys[0].RefTable = ImagesTable
UsersTable.ForeignKeys[1].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[0].RefTable = NotesTable
NoteMentionsTable.ForeignKeys[1].RefTable = UsersTable 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. // Image is the predicate function for image builders.
type Image func(*sql.Selector) 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. // Note is the predicate function for note builders.
type Note func(*sql.Selector) 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. // User is the predicate function for user builders.
type User func(*sql.Selector) type User func(*sql.Selector)

View file

@ -8,9 +8,10 @@ import (
"github.com/google/uuid" "github.com/google/uuid"
"github.com/lysand-org/versia-go/ent/attachment" "github.com/lysand-org/versia-go/ent/attachment"
"github.com/lysand-org/versia-go/ent/follow" "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/note"
"github.com/lysand-org/versia-go/ent/schema" "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/ent/user"
"github.com/lysand-org/versia-go/pkg/lysand" "github.com/lysand-org/versia-go/pkg/lysand"
) )
@ -77,6 +78,91 @@ func init() {
followDescID := followMixinFields0[0].Descriptor() followDescID := followMixinFields0[0].Descriptor()
// follow.DefaultID holds the default value on creation for the id field. // follow.DefaultID holds the default value on creation for the id field.
follow.DefaultID = followDescID.Default.(func() uuid.UUID) 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() noteMixin := schema.Note{}.Mixin()
noteMixinFields0 := noteMixin[0].Fields() noteMixinFields0 := noteMixin[0].Fields()
_ = noteMixinFields0 _ = noteMixinFields0
@ -112,45 +198,6 @@ func init() {
noteDescID := noteMixinFields0[0].Descriptor() noteDescID := noteMixinFields0[0].Descriptor()
// note.DefaultID holds the default value on creation for the id field. // note.DefaultID holds the default value on creation for the id field.
note.DefaultID = noteDescID.Default.(func() uuid.UUID) 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() userMixin := schema.User{}.Mixin()
userMixinFields0 := userMixin[0].Fields() userMixinFields0 := userMixin[0].Fields()
_ = userMixinFields0 _ = 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 is a validator for the "displayName" field. It is called by the builders before save.
user.DisplayNameValidator = userDescDisplayName.Validators[0].(func(string) error) user.DisplayNameValidator = userDescDisplayName.Validators[0].(func(string) error)
// userDescIndexable is the schema descriptor for indexable field. // 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 holds the default value on creation for the indexable field.
user.DefaultIndexable = userDescIndexable.Default.(bool) user.DefaultIndexable = userDescIndexable.Default.(bool)
// userDescFields is the schema descriptor for fields field. // 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 holds the default value on creation for the fields field.
user.DefaultFields = userDescFields.Default.([]lysand.Field) user.DefaultFields = userDescFields.Default.([]lysand.Field)
// userDescInbox is the schema descriptor for inbox 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 is a validator for the "inbox" field. It is called by the builders before save.
user.InboxValidator = userDescInbox.Validators[0].(func(string) error) user.InboxValidator = userDescInbox.Validators[0].(func(string) error)
// userDescFeatured is the schema descriptor for featured field. // 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 is a validator for the "featured" field. It is called by the builders before save.
user.FeaturedValidator = userDescFeatured.Validators[0].(func(string) error) user.FeaturedValidator = userDescFeatured.Validators[0].(func(string) error)
// userDescFollowers is the schema descriptor for followers field. // 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 is a validator for the "followers" field. It is called by the builders before save.
user.FollowersValidator = userDescFollowers.Validators[0].(func(string) error) user.FollowersValidator = userDescFollowers.Validators[0].(func(string) error)
// userDescFollowing is the schema descriptor for following field. // 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 is a validator for the "following" field. It is called by the builders before save.
user.FollowingValidator = userDescFollowing.Validators[0].(func(string) error) user.FollowingValidator = userDescFollowing.Validators[0].(func(string) error)
// userDescOutbox is the schema descriptor for outbox field. // 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 is a validator for the "outbox" field. It is called by the builders before save.
user.OutboxValidator = userDescOutbox.Validators[0].(func(string) error) user.OutboxValidator = userDescOutbox.Validators[0].(func(string) error)
// userDescID is the schema descriptor for id field. // userDescID is the schema descriptor for id field.

View file

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

View file

@ -11,7 +11,9 @@ type Follow struct{ ent.Schema }
func (Follow) Fields() []ent.Field { func (Follow) Fields() []ent.Field {
return []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 { func (Image) Fields() []ent.Field {
return []ent.Field{ return []ent.Field{
field.String("url"), field.String("url").Validate(ValidateURI),
field.String("mimeType"), 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 package schema
import ( import (
"crypto/ed25519"
"errors" "errors"
"regexp" "regexp"
@ -20,17 +19,31 @@ type User struct{ ent.Schema }
func (User) Fields() []ent.Field { func (User) Fields() []ent.Field {
return []ent.Field{ return []ent.Field{
field.String("username").Unique().MaxLen(32).Validate(ValidateUsername), field.String("username").
field.Bytes("passwordHash").Optional().Nillable(), Unique().
MaxLen(32).
Validate(ValidateUsername),
field.Bytes("passwordHash").
Optional().
Nillable(),
field.String("displayName").MaxLen(256).Optional().Nillable(), field.String("displayName").
field.String("biography").Optional().Nillable(), MaxLen(256).
Optional().
Nillable(),
field.String("biography").
Optional().
Nillable(),
field.Bytes("publicKey").GoType(ed25519.PublicKey([]byte{})), field.Bytes("publicKey"),
field.Bytes("privateKey").GoType(ed25519.PrivateKey([]byte{})).Optional(), field.String("publicKeyActor"),
field.String("publicKeyAlgorithm"),
field.Bytes("privateKey").Optional(),
field.Bool("indexable").Default(true), 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{}), 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("authoredNotes", Note.Type).Ref("author"),
edge.From("mentionedNotes", Note.Type).Ref("mentions"), 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 Follow *FollowClient
// Image is the client for interacting with the Image builders. // Image is the client for interacting with the Image builders.
Image *ImageClient 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 is the client for interacting with the Note builders.
Note *NoteClient 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 is the client for interacting with the User builders.
User *UserClient User *UserClient
@ -158,8 +158,8 @@ func (tx *Tx) init() {
tx.Attachment = NewAttachmentClient(tx.config) tx.Attachment = NewAttachmentClient(tx.config)
tx.Follow = NewFollowClient(tx.config) tx.Follow = NewFollowClient(tx.config)
tx.Image = NewImageClient(tx.config) tx.Image = NewImageClient(tx.config)
tx.InstanceMetadata = NewInstanceMetadataClient(tx.config)
tx.Note = NewNoteClient(tx.config) tx.Note = NewNoteClient(tx.config)
tx.ServerMetadata = NewServerMetadataClient(tx.config)
tx.User = NewUserClient(tx.config) tx.User = NewUserClient(tx.config)
} }

View file

@ -3,7 +3,6 @@
package ent package ent
import ( import (
"crypto/ed25519"
"encoding/json" "encoding/json"
"fmt" "fmt"
"strings" "strings"
@ -41,9 +40,13 @@ type User struct {
// Biography holds the value of the "biography" field. // Biography holds the value of the "biography" field.
Biography *string `json:"biography,omitempty"` Biography *string `json:"biography,omitempty"`
// PublicKey holds the value of the "publicKey" field. // 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 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 holds the value of the "indexable" field.
Indexable bool `json:"indexable,omitempty"` Indexable bool `json:"indexable,omitempty"`
// PrivacyLevel holds the value of the "privacyLevel" field. // PrivacyLevel holds the value of the "privacyLevel" field.
@ -78,9 +81,15 @@ type UserEdges struct {
AuthoredNotes []*Note `json:"authoredNotes,omitempty"` AuthoredNotes []*Note `json:"authoredNotes,omitempty"`
// MentionedNotes holds the value of the mentionedNotes edge. // MentionedNotes holds the value of the mentionedNotes edge.
MentionedNotes []*Note `json:"mentionedNotes,omitempty"` 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 // loadedTypes holds the information for reporting if a
// type was loaded (or requested) in eager-loading or not. // 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 // 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"} 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. // scanValues returns the types for scanning values from sql.Rows.
func (*User) scanValues(columns []string) ([]any, error) { func (*User) scanValues(columns []string) ([]any, error) {
values := make([]any, len(columns)) values := make([]any, len(columns))
@ -132,7 +168,7 @@ func (*User) scanValues(columns []string) ([]any, error) {
values[i] = new([]byte) values[i] = new([]byte)
case user.FieldIsRemote, user.FieldIndexable: case user.FieldIsRemote, user.FieldIndexable:
values[i] = new(sql.NullBool) 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) values[i] = new(sql.NullString)
case user.FieldCreatedAt, user.FieldUpdatedAt: case user.FieldCreatedAt, user.FieldUpdatedAt:
values[i] = new(sql.NullTime) values[i] = new(sql.NullTime)
@ -227,6 +263,18 @@ func (u *User) assignValues(columns []string, values []any) error {
} else if value != nil { } else if value != nil {
u.PublicKey = *value 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: case user.FieldPrivateKey:
if value, ok := values[i].(*[]byte); !ok { if value, ok := values[i].(*[]byte); !ok {
return fmt.Errorf("unexpected type %T for field privateKey", values[i]) 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) 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. // Update returns a builder for updating this User.
// Note that you need to call User.Unwrap() before calling this method if 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. // 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("publicKey=")
builder.WriteString(fmt.Sprintf("%v", u.PublicKey)) builder.WriteString(fmt.Sprintf("%v", u.PublicKey))
builder.WriteString(", ") 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("privateKey=")
builder.WriteString(fmt.Sprintf("%v", u.PrivateKey)) builder.WriteString(fmt.Sprintf("%v", u.PrivateKey))
builder.WriteString(", ") builder.WriteString(", ")

View file

@ -37,6 +37,10 @@ const (
FieldBiography = "biography" FieldBiography = "biography"
// FieldPublicKey holds the string denoting the publickey field in the database. // FieldPublicKey holds the string denoting the publickey field in the database.
FieldPublicKey = "public_key" 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 holds the string denoting the privatekey field in the database.
FieldPrivateKey = "private_key" FieldPrivateKey = "private_key"
// FieldIndexable holds the string denoting the indexable field in the database. // FieldIndexable holds the string denoting the indexable field in the database.
@ -63,6 +67,12 @@ const (
EdgeAuthoredNotes = "authoredNotes" EdgeAuthoredNotes = "authoredNotes"
// EdgeMentionedNotes holds the string denoting the mentionednotes edge name in mutations. // EdgeMentionedNotes holds the string denoting the mentionednotes edge name in mutations.
EdgeMentionedNotes = "mentionedNotes" 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 holds the table name of the user in the database.
Table = "users" Table = "users"
// AvatarImageTable is the table that holds the avatarImage relation/edge. // AvatarImageTable is the table that holds the avatarImage relation/edge.
@ -91,6 +101,21 @@ const (
// MentionedNotesInverseTable is the table name for the Note entity. // MentionedNotesInverseTable is the table name for the Note entity.
// It exists in this package in order to avoid circular dependency with the "note" package. // It exists in this package in order to avoid circular dependency with the "note" package.
MentionedNotesInverseTable = "notes" 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. // Columns holds all SQL columns for user fields.
@ -106,6 +131,8 @@ var Columns = []string{
FieldDisplayName, FieldDisplayName,
FieldBiography, FieldBiography,
FieldPublicKey, FieldPublicKey,
FieldPublicKeyActor,
FieldPublicKeyAlgorithm,
FieldPrivateKey, FieldPrivateKey,
FieldIndexable, FieldIndexable,
FieldPrivacyLevel, FieldPrivacyLevel,
@ -128,6 +155,15 @@ var (
// MentionedNotesPrimaryKey and MentionedNotesColumn2 are the table columns denoting the // MentionedNotesPrimaryKey and MentionedNotesColumn2 are the table columns denoting the
// primary key for the mentionedNotes relation (M2M). // primary key for the mentionedNotes relation (M2M).
MentionedNotesPrimaryKey = []string{"note_id", "user_id"} 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). // 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() 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. // ByIndexable orders the results by the indexable field.
func ByIndexable(opts ...sql.OrderTermOption) OrderOption { func ByIndexable(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldIndexable, opts...).ToFunc() 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...)...) 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 { func newAvatarImageStep() *sqlgraph.Step {
return sqlgraph.NewStep( return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID), sqlgraph.From(Table, FieldID),
@ -352,3 +440,24 @@ func newMentionedNotesStep() *sqlgraph.Step {
sqlgraph.Edge(sqlgraph.M2M, true, MentionedNotesTable, MentionedNotesPrimaryKey...), 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 package user
import ( import (
"crypto/ed25519"
"time" "time"
"entgo.io/ent/dialect/sql" "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. // PublicKey applies equality check predicate on the "publicKey" field. It's identical to PublicKeyEQ.
func PublicKey(v ed25519.PublicKey) predicate.User { func PublicKey(v []byte) predicate.User {
vc := []byte(v) return predicate.User(sql.FieldEQ(FieldPublicKey, v))
return predicate.User(sql.FieldEQ(FieldPublicKey, vc)) }
// 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. // PrivateKey applies equality check predicate on the "privateKey" field. It's identical to PrivateKeyEQ.
func PrivateKey(v ed25519.PrivateKey) predicate.User { func PrivateKey(v []byte) predicate.User {
vc := []byte(v) return predicate.User(sql.FieldEQ(FieldPrivateKey, v))
return predicate.User(sql.FieldEQ(FieldPrivateKey, vc))
} }
// Indexable applies equality check predicate on the "indexable" field. It's identical to IndexableEQ. // 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. // PublicKeyEQ applies the EQ predicate on the "publicKey" field.
func PublicKeyEQ(v ed25519.PublicKey) predicate.User { func PublicKeyEQ(v []byte) predicate.User {
vc := []byte(v) return predicate.User(sql.FieldEQ(FieldPublicKey, v))
return predicate.User(sql.FieldEQ(FieldPublicKey, vc))
} }
// PublicKeyNEQ applies the NEQ predicate on the "publicKey" field. // PublicKeyNEQ applies the NEQ predicate on the "publicKey" field.
func PublicKeyNEQ(v ed25519.PublicKey) predicate.User { func PublicKeyNEQ(v []byte) predicate.User {
vc := []byte(v) return predicate.User(sql.FieldNEQ(FieldPublicKey, v))
return predicate.User(sql.FieldNEQ(FieldPublicKey, vc))
} }
// PublicKeyIn applies the In predicate on the "publicKey" field. // PublicKeyIn applies the In predicate on the "publicKey" field.
func PublicKeyIn(vs ...ed25519.PublicKey) predicate.User { func PublicKeyIn(vs ...[]byte) predicate.User {
v := make([]any, len(vs)) return predicate.User(sql.FieldIn(FieldPublicKey, vs...))
for i := range v {
v[i] = []byte(vs[i])
}
return predicate.User(sql.FieldIn(FieldPublicKey, v...))
} }
// PublicKeyNotIn applies the NotIn predicate on the "publicKey" field. // PublicKeyNotIn applies the NotIn predicate on the "publicKey" field.
func PublicKeyNotIn(vs ...ed25519.PublicKey) predicate.User { func PublicKeyNotIn(vs ...[]byte) predicate.User {
v := make([]any, len(vs)) return predicate.User(sql.FieldNotIn(FieldPublicKey, vs...))
for i := range v {
v[i] = []byte(vs[i])
}
return predicate.User(sql.FieldNotIn(FieldPublicKey, v...))
} }
// PublicKeyGT applies the GT predicate on the "publicKey" field. // PublicKeyGT applies the GT predicate on the "publicKey" field.
func PublicKeyGT(v ed25519.PublicKey) predicate.User { func PublicKeyGT(v []byte) predicate.User {
vc := []byte(v) return predicate.User(sql.FieldGT(FieldPublicKey, v))
return predicate.User(sql.FieldGT(FieldPublicKey, vc))
} }
// PublicKeyGTE applies the GTE predicate on the "publicKey" field. // PublicKeyGTE applies the GTE predicate on the "publicKey" field.
func PublicKeyGTE(v ed25519.PublicKey) predicate.User { func PublicKeyGTE(v []byte) predicate.User {
vc := []byte(v) return predicate.User(sql.FieldGTE(FieldPublicKey, v))
return predicate.User(sql.FieldGTE(FieldPublicKey, vc))
} }
// PublicKeyLT applies the LT predicate on the "publicKey" field. // PublicKeyLT applies the LT predicate on the "publicKey" field.
func PublicKeyLT(v ed25519.PublicKey) predicate.User { func PublicKeyLT(v []byte) predicate.User {
vc := []byte(v) return predicate.User(sql.FieldLT(FieldPublicKey, v))
return predicate.User(sql.FieldLT(FieldPublicKey, vc))
} }
// PublicKeyLTE applies the LTE predicate on the "publicKey" field. // PublicKeyLTE applies the LTE predicate on the "publicKey" field.
func PublicKeyLTE(v ed25519.PublicKey) predicate.User { func PublicKeyLTE(v []byte) predicate.User {
vc := []byte(v) return predicate.User(sql.FieldLTE(FieldPublicKey, v))
return predicate.User(sql.FieldLTE(FieldPublicKey, vc)) }
// 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. // PrivateKeyEQ applies the EQ predicate on the "privateKey" field.
func PrivateKeyEQ(v ed25519.PrivateKey) predicate.User { func PrivateKeyEQ(v []byte) predicate.User {
vc := []byte(v) return predicate.User(sql.FieldEQ(FieldPrivateKey, v))
return predicate.User(sql.FieldEQ(FieldPrivateKey, vc))
} }
// PrivateKeyNEQ applies the NEQ predicate on the "privateKey" field. // PrivateKeyNEQ applies the NEQ predicate on the "privateKey" field.
func PrivateKeyNEQ(v ed25519.PrivateKey) predicate.User { func PrivateKeyNEQ(v []byte) predicate.User {
vc := []byte(v) return predicate.User(sql.FieldNEQ(FieldPrivateKey, v))
return predicate.User(sql.FieldNEQ(FieldPrivateKey, vc))
} }
// PrivateKeyIn applies the In predicate on the "privateKey" field. // PrivateKeyIn applies the In predicate on the "privateKey" field.
func PrivateKeyIn(vs ...ed25519.PrivateKey) predicate.User { func PrivateKeyIn(vs ...[]byte) predicate.User {
v := make([]any, len(vs)) return predicate.User(sql.FieldIn(FieldPrivateKey, vs...))
for i := range v {
v[i] = []byte(vs[i])
}
return predicate.User(sql.FieldIn(FieldPrivateKey, v...))
} }
// PrivateKeyNotIn applies the NotIn predicate on the "privateKey" field. // PrivateKeyNotIn applies the NotIn predicate on the "privateKey" field.
func PrivateKeyNotIn(vs ...ed25519.PrivateKey) predicate.User { func PrivateKeyNotIn(vs ...[]byte) predicate.User {
v := make([]any, len(vs)) return predicate.User(sql.FieldNotIn(FieldPrivateKey, vs...))
for i := range v {
v[i] = []byte(vs[i])
}
return predicate.User(sql.FieldNotIn(FieldPrivateKey, v...))
} }
// PrivateKeyGT applies the GT predicate on the "privateKey" field. // PrivateKeyGT applies the GT predicate on the "privateKey" field.
func PrivateKeyGT(v ed25519.PrivateKey) predicate.User { func PrivateKeyGT(v []byte) predicate.User {
vc := []byte(v) return predicate.User(sql.FieldGT(FieldPrivateKey, v))
return predicate.User(sql.FieldGT(FieldPrivateKey, vc))
} }
// PrivateKeyGTE applies the GTE predicate on the "privateKey" field. // PrivateKeyGTE applies the GTE predicate on the "privateKey" field.
func PrivateKeyGTE(v ed25519.PrivateKey) predicate.User { func PrivateKeyGTE(v []byte) predicate.User {
vc := []byte(v) return predicate.User(sql.FieldGTE(FieldPrivateKey, v))
return predicate.User(sql.FieldGTE(FieldPrivateKey, vc))
} }
// PrivateKeyLT applies the LT predicate on the "privateKey" field. // PrivateKeyLT applies the LT predicate on the "privateKey" field.
func PrivateKeyLT(v ed25519.PrivateKey) predicate.User { func PrivateKeyLT(v []byte) predicate.User {
vc := []byte(v) return predicate.User(sql.FieldLT(FieldPrivateKey, v))
return predicate.User(sql.FieldLT(FieldPrivateKey, vc))
} }
// PrivateKeyLTE applies the LTE predicate on the "privateKey" field. // PrivateKeyLTE applies the LTE predicate on the "privateKey" field.
func PrivateKeyLTE(v ed25519.PrivateKey) predicate.User { func PrivateKeyLTE(v []byte) predicate.User {
vc := []byte(v) return predicate.User(sql.FieldLTE(FieldPrivateKey, v))
return predicate.User(sql.FieldLTE(FieldPrivateKey, vc))
} }
// PrivateKeyIsNil applies the IsNil predicate on the "privateKey" field. // 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. // And groups predicates with the AND operator between them.
func And(predicates ...predicate.User) predicate.User { func And(predicates ...predicate.User) predicate.User {
return predicate.User(sql.AndPredicates(predicates...)) return predicate.User(sql.AndPredicates(predicates...))

View file

@ -4,7 +4,6 @@ package ent
import ( import (
"context" "context"
"crypto/ed25519"
"errors" "errors"
"fmt" "fmt"
"time" "time"
@ -15,6 +14,7 @@ import (
"entgo.io/ent/schema/field" "entgo.io/ent/schema/field"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/lysand-org/versia-go/ent/image" "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/note"
"github.com/lysand-org/versia-go/ent/user" "github.com/lysand-org/versia-go/ent/user"
"github.com/lysand-org/versia-go/pkg/lysand" "github.com/lysand-org/versia-go/pkg/lysand"
@ -115,14 +115,26 @@ func (uc *UserCreate) SetNillableBiography(s *string) *UserCreate {
} }
// SetPublicKey sets the "publicKey" field. // SetPublicKey sets the "publicKey" field.
func (uc *UserCreate) SetPublicKey(ek ed25519.PublicKey) *UserCreate { func (uc *UserCreate) SetPublicKey(b []byte) *UserCreate {
uc.mutation.SetPublicKey(ek) 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 return uc
} }
// SetPrivateKey sets the "privateKey" field. // SetPrivateKey sets the "privateKey" field.
func (uc *UserCreate) SetPrivateKey(ek ed25519.PrivateKey) *UserCreate { func (uc *UserCreate) SetPrivateKey(b []byte) *UserCreate {
uc.mutation.SetPrivateKey(ek) uc.mutation.SetPrivateKey(b)
return uc return uc
} }
@ -272,6 +284,51 @@ func (uc *UserCreate) AddMentionedNotes(n ...*Note) *UserCreate {
return uc.AddMentionedNoteIDs(ids...) 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. // Mutation returns the UserMutation object of the builder.
func (uc *UserCreate) Mutation() *UserMutation { func (uc *UserCreate) Mutation() *UserMutation {
return uc.mutation return uc.mutation
@ -375,6 +432,12 @@ func (uc *UserCreate) check() error {
if _, ok := uc.mutation.PublicKey(); !ok { if _, ok := uc.mutation.PublicKey(); !ok {
return &ValidationError{Name: "publicKey", err: errors.New(`ent: missing required field "User.publicKey"`)} 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 { if _, ok := uc.mutation.Indexable(); !ok {
return &ValidationError{Name: "indexable", err: errors.New(`ent: missing required field "User.indexable"`)} 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) _spec.SetField(user.FieldPublicKey, field.TypeBytes, value)
_node.PublicKey = 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 { if value, ok := uc.mutation.PrivateKey(); ok {
_spec.SetField(user.FieldPrivateKey, field.TypeBytes, value) _spec.SetField(user.FieldPrivateKey, field.TypeBytes, value)
_node.PrivateKey = value _node.PrivateKey = value
@ -607,6 +678,54 @@ func (uc *UserCreate) createSpec() (*User, *sqlgraph.CreateSpec) {
} }
_spec.Edges = append(_spec.Edges, edge) _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 return _node, _spec
} }
@ -774,7 +893,7 @@ func (u *UserUpsert) ClearBiography() *UserUpsert {
} }
// SetPublicKey sets the "publicKey" field. // 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) u.Set(user.FieldPublicKey, v)
return u return u
} }
@ -785,8 +904,32 @@ func (u *UserUpsert) UpdatePublicKey() *UserUpsert {
return u 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. // 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) u.Set(user.FieldPrivateKey, v)
return u return u
} }
@ -1084,7 +1227,7 @@ func (u *UserUpsertOne) ClearBiography() *UserUpsertOne {
} }
// SetPublicKey sets the "publicKey" field. // 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) { return u.Update(func(s *UserUpsert) {
s.SetPublicKey(v) 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. // 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) { return u.Update(func(s *UserUpsert) {
s.SetPrivateKey(v) s.SetPrivateKey(v)
}) })
@ -1582,7 +1753,7 @@ func (u *UserUpsertBulk) ClearBiography() *UserUpsertBulk {
} }
// SetPublicKey sets the "publicKey" field. // 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) { return u.Update(func(s *UserUpsert) {
s.SetPublicKey(v) 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. // 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) { return u.Update(func(s *UserUpsert) {
s.SetPrivateKey(v) s.SetPrivateKey(v)
}) })

View file

@ -13,6 +13,7 @@ import (
"entgo.io/ent/schema/field" "entgo.io/ent/schema/field"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/lysand-org/versia-go/ent/image" "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/note"
"github.com/lysand-org/versia-go/ent/predicate" "github.com/lysand-org/versia-go/ent/predicate"
"github.com/lysand-org/versia-go/ent/user" "github.com/lysand-org/versia-go/ent/user"
@ -29,6 +30,9 @@ type UserQuery struct {
withHeaderImage *ImageQuery withHeaderImage *ImageQuery
withAuthoredNotes *NoteQuery withAuthoredNotes *NoteQuery
withMentionedNotes *NoteQuery withMentionedNotes *NoteQuery
withServers *InstanceMetadataQuery
withModeratedServers *InstanceMetadataQuery
withAdministeredServers *InstanceMetadataQuery
withFKs bool withFKs bool
// intermediate query (i.e. traversal path). // intermediate query (i.e. traversal path).
sql *sql.Selector sql *sql.Selector
@ -154,6 +158,72 @@ func (uq *UserQuery) QueryMentionedNotes() *NoteQuery {
return query 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. // First returns the first User entity from the query.
// Returns a *NotFoundError when no User was found. // Returns a *NotFoundError when no User was found.
func (uq *UserQuery) First(ctx context.Context) (*User, error) { func (uq *UserQuery) First(ctx context.Context) (*User, error) {
@ -350,6 +420,9 @@ func (uq *UserQuery) Clone() *UserQuery {
withHeaderImage: uq.withHeaderImage.Clone(), withHeaderImage: uq.withHeaderImage.Clone(),
withAuthoredNotes: uq.withAuthoredNotes.Clone(), withAuthoredNotes: uq.withAuthoredNotes.Clone(),
withMentionedNotes: uq.withMentionedNotes.Clone(), withMentionedNotes: uq.withMentionedNotes.Clone(),
withServers: uq.withServers.Clone(),
withModeratedServers: uq.withModeratedServers.Clone(),
withAdministeredServers: uq.withAdministeredServers.Clone(),
// clone intermediate query. // clone intermediate query.
sql: uq.sql.Clone(), sql: uq.sql.Clone(),
path: uq.path, path: uq.path,
@ -400,6 +473,39 @@ func (uq *UserQuery) WithMentionedNotes(opts ...func(*NoteQuery)) *UserQuery {
return uq 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. // 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. // 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{} nodes = []*User{}
withFKs = uq.withFKs withFKs = uq.withFKs
_spec = uq.querySpec() _spec = uq.querySpec()
loadedTypes = [4]bool{ loadedTypes = [7]bool{
uq.withAvatarImage != nil, uq.withAvatarImage != nil,
uq.withHeaderImage != nil, uq.withHeaderImage != nil,
uq.withAuthoredNotes != nil, uq.withAuthoredNotes != nil,
uq.withMentionedNotes != nil, uq.withMentionedNotes != nil,
uq.withServers != nil,
uq.withModeratedServers != nil,
uq.withAdministeredServers != nil,
} }
) )
if uq.withAvatarImage != nil || uq.withHeaderImage != 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 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 return nodes, nil
} }
@ -695,6 +827,189 @@ func (uq *UserQuery) loadMentionedNotes(ctx context.Context, query *NoteQuery, n
} }
return nil 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) { func (uq *UserQuery) sqlCount(ctx context.Context) (int, error) {
_spec := uq.querySpec() _spec := uq.querySpec()

View file

@ -4,7 +4,6 @@ package ent
import ( import (
"context" "context"
"crypto/ed25519"
"errors" "errors"
"fmt" "fmt"
"time" "time"
@ -15,6 +14,7 @@ import (
"entgo.io/ent/schema/field" "entgo.io/ent/schema/field"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/lysand-org/versia-go/ent/image" "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/note"
"github.com/lysand-org/versia-go/ent/predicate" "github.com/lysand-org/versia-go/ent/predicate"
"github.com/lysand-org/versia-go/ent/user" "github.com/lysand-org/versia-go/ent/user"
@ -141,14 +141,42 @@ func (uu *UserUpdate) ClearBiography() *UserUpdate {
} }
// SetPublicKey sets the "publicKey" field. // SetPublicKey sets the "publicKey" field.
func (uu *UserUpdate) SetPublicKey(ek ed25519.PublicKey) *UserUpdate { func (uu *UserUpdate) SetPublicKey(b []byte) *UserUpdate {
uu.mutation.SetPublicKey(ek) 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 return uu
} }
// SetPrivateKey sets the "privateKey" field. // SetPrivateKey sets the "privateKey" field.
func (uu *UserUpdate) SetPrivateKey(ek ed25519.PrivateKey) *UserUpdate { func (uu *UserUpdate) SetPrivateKey(b []byte) *UserUpdate {
uu.mutation.SetPrivateKey(ek) uu.mutation.SetPrivateKey(b)
return uu return uu
} }
@ -336,6 +364,51 @@ func (uu *UserUpdate) AddMentionedNotes(n ...*Note) *UserUpdate {
return uu.AddMentionedNoteIDs(ids...) 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. // Mutation returns the UserMutation object of the builder.
func (uu *UserUpdate) Mutation() *UserMutation { func (uu *UserUpdate) Mutation() *UserMutation {
return uu.mutation return uu.mutation
@ -395,6 +468,69 @@ func (uu *UserUpdate) RemoveMentionedNotes(n ...*Note) *UserUpdate {
return uu.RemoveMentionedNoteIDs(ids...) 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. // Save executes the query and returns the number of nodes affected by the update operation.
func (uu *UserUpdate) Save(ctx context.Context) (int, error) { func (uu *UserUpdate) Save(ctx context.Context) (int, error) {
uu.defaults() uu.defaults()
@ -529,6 +665,12 @@ func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) {
if value, ok := uu.mutation.PublicKey(); ok { if value, ok := uu.mutation.PublicKey(); ok {
_spec.SetField(user.FieldPublicKey, field.TypeBytes, value) _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 { if value, ok := uu.mutation.PrivateKey(); ok {
_spec.SetField(user.FieldPrivateKey, field.TypeBytes, value) _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) _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 n, err = sqlgraph.UpdateNodes(ctx, uu.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok { if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{user.Label} err = &NotFoundError{user.Label}
@ -839,14 +1116,42 @@ func (uuo *UserUpdateOne) ClearBiography() *UserUpdateOne {
} }
// SetPublicKey sets the "publicKey" field. // SetPublicKey sets the "publicKey" field.
func (uuo *UserUpdateOne) SetPublicKey(ek ed25519.PublicKey) *UserUpdateOne { func (uuo *UserUpdateOne) SetPublicKey(b []byte) *UserUpdateOne {
uuo.mutation.SetPublicKey(ek) 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 return uuo
} }
// SetPrivateKey sets the "privateKey" field. // SetPrivateKey sets the "privateKey" field.
func (uuo *UserUpdateOne) SetPrivateKey(ek ed25519.PrivateKey) *UserUpdateOne { func (uuo *UserUpdateOne) SetPrivateKey(b []byte) *UserUpdateOne {
uuo.mutation.SetPrivateKey(ek) uuo.mutation.SetPrivateKey(b)
return uuo return uuo
} }
@ -1034,6 +1339,51 @@ func (uuo *UserUpdateOne) AddMentionedNotes(n ...*Note) *UserUpdateOne {
return uuo.AddMentionedNoteIDs(ids...) 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. // Mutation returns the UserMutation object of the builder.
func (uuo *UserUpdateOne) Mutation() *UserMutation { func (uuo *UserUpdateOne) Mutation() *UserMutation {
return uuo.mutation return uuo.mutation
@ -1093,6 +1443,69 @@ func (uuo *UserUpdateOne) RemoveMentionedNotes(n ...*Note) *UserUpdateOne {
return uuo.RemoveMentionedNoteIDs(ids...) 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. // Where appends a list predicates to the UserUpdate builder.
func (uuo *UserUpdateOne) Where(ps ...predicate.User) *UserUpdateOne { func (uuo *UserUpdateOne) Where(ps ...predicate.User) *UserUpdateOne {
uuo.mutation.Where(ps...) 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 { if value, ok := uuo.mutation.PublicKey(); ok {
_spec.SetField(user.FieldPublicKey, field.TypeBytes, value) _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 { if value, ok := uuo.mutation.PrivateKey(); ok {
_spec.SetField(user.FieldPrivateKey, field.TypeBytes, value) _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) _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} _node = &User{config: uuo.config}
_spec.Assign = _node.assignValues _spec.Assign = _node.assignValues
_spec.ScanValues = _node.scanValues _spec.ScanValues = _node.scanValues

View file

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

View file

@ -2,6 +2,7 @@ package api_schema
import ( import (
"github.com/google/uuid" "github.com/google/uuid"
"github.com/lysand-org/versia-go/pkg/lysand"
) )
type User struct { type User struct {
@ -9,9 +10,16 @@ type User struct {
Username string `json:"username"` Username string `json:"username"`
} }
type LysandUser lysand.User
type FetchUserResponse = APIResponse[User] type FetchUserResponse = APIResponse[User]
type CreateUserRequest struct { 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"` 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 ( import (
"github.com/lysand-org/versia-go/internal/helpers" "github.com/lysand-org/versia-go/internal/helpers"
versiacrypto "github.com/lysand-org/versia-go/pkg/lysand/crypto"
"net/url" "net/url"
"github.com/lysand-org/versia-go/ent" "github.com/lysand-org/versia-go/ent"
@ -13,6 +14,8 @@ type User struct {
*ent.User *ent.User
URI *lysand.URL URI *lysand.URL
PKActorURI *lysand.URL
PublicKey *lysand.SPKIPublicKey
Inbox *lysand.URL Inbox *lysand.URL
Outbox *lysand.URL Outbox *lysand.URL
Featured *lysand.URL Featured *lysand.URL
@ -25,38 +28,52 @@ type User struct {
Signer lysand.Signer Signer lysand.Signer
} }
func NewUser(dbUser *ent.User) (*User, error) { func NewUser(dbData *ent.User) (*User, error) {
u := &User{User: dbUser} u := &User{
User: dbData,
PublicKey: &lysand.SPKIPublicKey{
Key: nil,
Algorithm: dbData.PublicKeyAlgorithm,
},
DisplayName: dbData.Username,
u.DisplayName = u.Username LysandAvatar: lysandAvatar(dbData),
if dbUser.DisplayName != nil { LysandBiography: lysandBiography(dbData),
u.DisplayName = *dbUser.DisplayName }
if dbData.DisplayName != nil {
u.DisplayName = *dbData.DisplayName
} }
var err error var err error
if u.URI, err = lysand.ParseURL(dbUser.URI); err != nil { if u.PublicKey.Key, err = versiacrypto.ToTypedKey(dbData.PublicKeyAlgorithm, dbData.PublicKey); err != nil {
return nil, err return nil, err
} }
if u.Inbox, err = lysand.ParseURL(dbUser.Inbox); err != nil {
return nil, err if u.URI, err = lysand.ParseURL(dbData.URI); err != nil {
} return nil, err
if u.Outbox, err = lysand.ParseURL(dbUser.Outbox); err != nil { }
return nil, err if u.PKActorURI, err = lysand.ParseURL(dbData.PublicKeyActor); err != nil {
} return nil, err
if u.Featured, err = lysand.ParseURL(dbUser.Featured); err != nil { }
return nil, err if u.Inbox, err = lysand.ParseURL(dbData.Inbox); err != nil {
} return nil, err
if u.Followers, err = lysand.ParseURL(dbUser.Followers); err != nil { }
return nil, err if u.Outbox, err = lysand.ParseURL(dbData.Outbox); err != nil {
} return nil, err
if u.Following, err = lysand.ParseURL(dbUser.Following); err != nil { }
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 return nil, err
} }
u.LysandAvatar = lysandAvatar(dbUser)
u.LysandBiography = lysandBiography(dbUser)
u.Signer = lysand.Signer{ u.Signer = lysand.Signer{
PrivateKey: dbUser.PrivateKey, PrivateKey: dbData.PrivateKey,
UserURL: u.URI.ToStd(), UserURL: u.URI.ToStd(),
} }
@ -76,9 +93,10 @@ func (u User) ToLysand() *lysand.User {
Avatar: u.LysandAvatar, Avatar: u.LysandAvatar,
Header: imageMap(u.Edges.HeaderImage), Header: imageMap(u.Edges.HeaderImage),
Indexable: u.Indexable, Indexable: u.Indexable,
PublicKey: lysand.PublicKey{ PublicKey: lysand.UserPublicKey{
Actor: utils.UserAPIURL(u.ID), Actor: u.PKActorURI,
PublicKey: lysand.SPKIPublicKey(u.PublicKey), Algorithm: u.PublicKeyAlgorithm,
Key: u.PublicKey,
}, },
Bio: u.LysandBiography, Bio: u.LysandBiography,
Fields: u.Fields, Fields: u.Fields,
@ -88,10 +106,6 @@ func (u User) ToLysand() *lysand.User {
Featured: u.Featured, Featured: u.Featured,
Followers: u.Followers, Followers: u.Followers,
Following: u.Following, 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/go-logr/logr"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"github.com/lysand-org/versia-go/config" "github.com/lysand-org/versia-go/config"
"github.com/lysand-org/versia-go/internal/service"
"github.com/lysand-org/versia-go/pkg/webfinger" "github.com/lysand-org/versia-go/pkg/webfinger"
) )
type Handler struct { type Handler struct {
instanceMetadataService service.InstanceMetadataService
hostMeta webfinger.HostMeta hostMeta webfinger.HostMeta
log logr.Logger log logr.Logger
} }
func New(log logr.Logger) *Handler { func New(instanceMetadataService service.InstanceMetadataService, log logr.Logger) *Handler {
return &Handler{ return &Handler{
instanceMetadataService: instanceMetadataService,
hostMeta: webfinger.NewHostMeta(config.C.PublicAddress), hostMeta: webfinger.NewHostMeta(config.C.PublicAddress),
log: log.WithName("users"), log: log.WithName("users"),
@ -22,7 +27,11 @@ func New(log logr.Logger) *Handler {
} }
func (i *Handler) Register(r fiber.Router) { 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", i.GetHostMeta)
r.Get("/.well-known/host-meta.json", i.GetHostMetaJSON) 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,8 +8,10 @@ import (
) )
type Handler struct { type Handler struct {
userService service.UserService
federationService service.FederationService federationService service.FederationService
requestSigner service.RequestSigner
userService service.UserService
inboxService service.InboxService inboxService service.InboxService
bodyValidator validators.BodyValidator bodyValidator validators.BodyValidator
@ -18,10 +20,12 @@ type Handler struct {
log logr.Logger 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{ return &Handler{
userService: userService,
federationService: federationService, federationService: federationService,
requestSigner: requestSigner,
userService: userService,
inboxService: inboxService, inboxService: inboxService,
bodyValidator: bodyValidator, bodyValidator: bodyValidator,
@ -41,6 +45,7 @@ func (i *Handler) Register(r fiber.Router) {
r.Get("/api/app/users/:id", i.GetUser) r.Get("/api/app/users/:id", i.GetUser)
r.Post("/api/app/users/", i.CreateUser) r.Post("/api/app/users/", i.CreateUser)
r.Get("/api/users/search", i.SearchUser)
r.Get("/api/users/:id", i.GetLysandUser) r.Get("/api/users/:id", i.GetLysandUser)
r.Post("/api/users/:id/inbox", i.LysandInbox) 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 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 package user_handler
import ( import (
"errors"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"github.com/lysand-org/versia-go/config" "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/internal/helpers"
"github.com/lysand-org/versia-go/pkg/webfinger" "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 { 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"), Error: helpers.StringPtr("The requested user is a remote user"),
}) })
} }
wf, err := i.userService.GetWebfingerForUser(c.UserContext(), userID.ID) wf, err := i.userService.GetWebfingerForUser(c.UserContext(), userID.ID)
if err != nil { 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{ return c.Status(fiber.StatusInternalServerError).JSON(webfinger.Response{
Error: helpers.StringPtr("Failed to query user"), 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) { 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) AddAttribute("followID", id)
defer s.End() defer s.End()
ctx = s.Context() 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) { 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("follower", follower.URI).
AddAttribute("followee", followee.URI) AddAttribute("followee", followee.URI)
defer s.End() 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 { 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("follower", follower.URI).
AddAttribute("followee", followee.URI) AddAttribute("followee", followee.URI)
defer s.End() 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 { 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("follower", follower.URI).
AddAttribute("followee", followee.URI) AddAttribute("followee", followee.URI)
defer s.End() 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 { 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("follower", follower.URI).
AddAttribute("followee", followee.URI) AddAttribute("followee", followee.URI)
defer s.End() 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

@ -18,29 +18,35 @@ type ManagerImpl struct {
users repository.UserRepository users repository.UserRepository
notes repository.NoteRepository notes repository.NoteRepository
follows repository.FollowRepository follows repository.FollowRepository
instanceMetadata repository.InstanceMetadataRepository
uRFactory Factory[repository.UserRepository] uRFactory Factory[repository.UserRepository]
nRFactory Factory[repository.NoteRepository] nRFactory Factory[repository.NoteRepository]
fRFactory Factory[repository.FollowRepository] fRFactory Factory[repository.FollowRepository]
imRFactory Factory[repository.InstanceMetadataRepository]
db *ent.Client db *ent.Client
log logr.Logger log logr.Logger
telemetry *unitel.Telemetry 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 { func NewManagerImpl(
userRepository := userRepositoryFunc(db, log.WithName("users"), telemetry) db *ent.Client, telemetry *unitel.Telemetry, log logr.Logger,
noteRepository := noteRepositoryFunc(db, log.WithName("notes"), telemetry) userRepositoryFunc Factory[repository.UserRepository],
followRepository := followRepositoryFunc(db, log.WithName("follows"), telemetry) noteRepositoryFunc Factory[repository.NoteRepository],
followRepositoryFunc Factory[repository.FollowRepository],
instanceMetadataRepositoryFunc Factory[repository.InstanceMetadataRepository],
) *ManagerImpl {
return &ManagerImpl{ return &ManagerImpl{
users: userRepository, users: userRepositoryFunc(db, log.WithName("users"), telemetry),
notes: noteRepository, notes: noteRepositoryFunc(db, log.WithName("notes"), telemetry),
follows: followRepository, follows: followRepositoryFunc(db, log.WithName("follows"), telemetry),
instanceMetadata: instanceMetadataRepositoryFunc(db, log.WithName("instanceMetadata"), telemetry),
uRFactory: userRepositoryFunc, uRFactory: userRepositoryFunc,
nRFactory: noteRepositoryFunc, nRFactory: noteRepositoryFunc,
fRFactory: followRepositoryFunc, fRFactory: followRepositoryFunc,
imRFactory: instanceMetadataRepositoryFunc,
db: db, db: db,
log: log, 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 { 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 { 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() defer s.End()
ctx = s.Context() ctx = s.Context()
@ -88,3 +100,7 @@ func (i *ManagerImpl) Notes() repository.NoteRepository {
func (i *ManagerImpl) Follows() repository.FollowRepository { func (i *ManagerImpl) Follows() repository.FollowRepository {
return i.follows 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) { 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() defer s.End()
ctx = s.Context() 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) { 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() defer s.End()
ctx = s.Context() 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) { 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() defer s.End()
ctx = s.Context() ctx = s.Context()

View file

@ -4,6 +4,7 @@ import (
"context" "context"
"crypto/ed25519" "crypto/ed25519"
"errors" "errors"
"github.com/lysand-org/versia-go/config"
"github.com/lysand-org/versia-go/internal/repository" "github.com/lysand-org/versia-go/internal/repository"
"github.com/lysand-org/versia-go/internal/service" "github.com/lysand-org/versia-go/internal/service"
"golang.org/x/crypto/bcrypt" "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) { 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() defer s.End()
ctx = s.Context() ctx = s.Context()
@ -62,8 +63,10 @@ func (i *UserRepositoryImpl) NewUser(ctx context.Context, username, password str
SetURI(utils.UserAPIURL(uid).String()). SetURI(utils.UserAPIURL(uid).String()).
SetUsername(username). SetUsername(username).
SetPasswordHash(pwHash). SetPasswordHash(pwHash).
SetPublicKey(pub).
SetPrivateKey(priv). SetPrivateKey(priv).
SetPublicKey(pub).
SetPublicKeyAlgorithm("ed25519").
SetPublicKeyActor(utils.UserAPIURL(uid).String()).
SetInbox(utils.UserInboxAPIURL(uid).String()). SetInbox(utils.UserInboxAPIURL(uid).String()).
SetOutbox(utils.UserOutboxAPIURL(uid).String()). SetOutbox(utils.UserOutboxAPIURL(uid).String()).
SetFeatured(utils.UserFeaturedAPIURL(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) { 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() defer s.End()
ctx = s.Context() ctx = s.Context()
@ -99,7 +102,9 @@ func (i *UserRepositoryImpl) ImportLysandUserByURI(ctx context.Context, uri *lys
SetUsername(lUser.Username). SetUsername(lUser.Username).
SetNillableDisplayName(lUser.DisplayName). SetNillableDisplayName(lUser.DisplayName).
SetBiography(lUser.Bio.String()). 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). SetIndexable(lUser.Indexable).
SetFields(lUser.Fields). SetFields(lUser.Fields).
SetExtensions(lUser.Extensions). SetExtensions(lUser.Extensions).
@ -127,11 +132,66 @@ func (i *UserRepositoryImpl) ImportLysandUserByURI(ctx context.Context, uri *lys
return entity.NewUser(u) return entity.NewUser(u)
} }
func (i *UserRepositoryImpl) Resolve(ctx context.Context, uri *lysand.URL) (*entity.User, error) { func (i *UserRepositoryImpl) Discover(ctx context.Context, domain, username string) (*entity.User, error) {
s := i.telemetry.StartSpan(ctx, "function", "repository/repo_impls.UserRepositoryImpl.Resolve") s := i.telemetry.StartSpan(ctx, "function", "svc_impls/UserServiceImpl.Search").
AddAttribute("username", username).
AddAttribute("domain", domain)
defer s.End() defer s.End()
ctx = s.Context() 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) u, err := i.LookupByURI(ctx, uri)
if err != nil { if err != nil {
return nil, err 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 // check if the user is already imported
if u == nil { 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) u, err := i.ImportLysandUserByURI(ctx, uri)
if err != nil { if err != nil {
i.log.Error(err, "Failed to import user", "uri", uri) l.Error(err, "Failed to import user")
return nil, err return nil, err
} }
return u, nil 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 return u, nil
} }
func (i *UserRepositoryImpl) ResolveMultiple(ctx context.Context, uris []lysand.URL) ([]*entity.User, error) { 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() defer s.End()
ctx = s.Context() 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 // TODO: Refactor to use async imports using a work queue
outer: outer:
for _, uri := range uris { for _, uri := range uris {
l := i.log.WithValues("uri", uri)
// check if the user is already imported // check if the user is already imported
for _, u := range us { for _, u := range us {
if uri.String() == u.URI.String() { 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 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) importedUser, err := i.ImportLysandUserByURI(ctx, &uri)
if err != nil { if err != nil {
i.log.Error(err, "Failed to import user", "uri", uri) l.Error(err, "Failed to import user")
continue continue
} }
i.log.V(2).Info("Imported user", "uri", uri) l.V(2).Info("Imported user")
us = append(us, importedUser) us = append(us, importedUser)
} }
@ -195,10 +257,12 @@ outer:
} }
func (i *UserRepositoryImpl) GetByID(ctx context.Context, uid uuid.UUID) (*entity.User, error) { 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() defer s.End()
ctx = s.Context() ctx = s.Context()
l := i.log.WithValues("id", uid)
u, err := i.db.User.Query(). u, err := i.db.User.Query().
Where(user.IDEQ(uid)). Where(user.IDEQ(uid)).
WithAvatarImage(). WithAvatarImage().
@ -206,25 +270,27 @@ func (i *UserRepositoryImpl) GetByID(ctx context.Context, uid uuid.UUID) (*entit
Only(ctx) Only(ctx)
if err != nil { if err != nil {
if !ent.IsNotFound(err) { if !ent.IsNotFound(err) {
i.log.Error(err, "Failed to query user", "id", uid) l.Error(err, "Failed to query user")
return nil, err 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 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) return entity.NewUser(u)
} }
func (i *UserRepositoryImpl) GetLocalByID(ctx context.Context, uid uuid.UUID) (*entity.User, error) { 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() defer s.End()
ctx = s.Context() ctx = s.Context()
l := i.log.WithValues("id", uid)
u, err := i.db.User.Query(). u, err := i.db.User.Query().
Where(user.And(user.ID(uid), user.IsRemote(false))). Where(user.And(user.ID(uid), user.IsRemote(false))).
WithAvatarImage(). WithAvatarImage().
@ -232,47 +298,77 @@ func (i *UserRepositoryImpl) GetLocalByID(ctx context.Context, uid uuid.UUID) (*
Only(ctx) Only(ctx)
if err != nil { if err != nil {
if !ent.IsNotFound(err) { 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 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 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) return entity.NewUser(u)
} }
func (i *UserRepositoryImpl) LookupByURI(ctx context.Context, uri *lysand.URL) (*entity.User, error) { 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() defer s.End()
ctx = s.Context() ctx = s.Context()
l := i.log.WithValues("uri", uri)
// check if the user is already imported // check if the user is already imported
u, err := i.db.User.Query(). u, err := i.db.User.Query().
Where(user.URI(uri.String())). Where(user.URI(uri.String())).
Only(ctx) Only(ctx)
if err != nil { if err != nil {
if !ent.IsNotFound(err) { if !ent.IsNotFound(err) {
i.log.Error(err, "Failed to query user", "uri", uri) l.Error(err, "Failed to query user")
return nil, err 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 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) return entity.NewUser(u)
} }
func (i *UserRepositoryImpl) LookupByURIs(ctx context.Context, uris []lysand.URL) ([]*entity.User, error) { 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() defer s.End()
ctx = s.Context() 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) { 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() defer s.End()
ctx = s.Context() ctx = s.Context()
@ -303,6 +399,8 @@ func (i *UserRepositoryImpl) LookupByIDOrUsername(ctx context.Context, idOrUsern
preds = append(preds, user.UsernameEQ(idOrUsername)) preds = append(preds, user.UsernameEQ(idOrUsername))
} }
l := i.log.WithValues("idOrUsername", idOrUsername)
u, err := i.db.User.Query(). u, err := i.db.User.Query().
Where(preds...). Where(preds...).
WithAvatarImage(). WithAvatarImage().
@ -310,16 +408,16 @@ func (i *UserRepositoryImpl) LookupByIDOrUsername(ctx context.Context, idOrUsern
Only(ctx) Only(ctx)
if err != nil { if err != nil {
if !ent.IsNotFound(err) { if !ent.IsNotFound(err) {
i.log.Error(err, "Failed to query user", "idOrUsername", idOrUsername) l.Error(err, "Failed to query user")
return nil, err 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 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) return entity.NewUser(u)
} }

View file

@ -15,6 +15,9 @@ type UserRepository interface {
GetByID(ctx context.Context, id uuid.UUID) (*entity.User, error) GetByID(ctx context.Context, id uuid.UUID) (*entity.User, error)
GetLocalByID(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) Resolve(ctx context.Context, uri *lysand.URL) (*entity.User, error)
ResolveMultiple(ctx context.Context, uris []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) 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 { type Manager interface {
Atomic(ctx context.Context, fn func(ctx context.Context, tx Manager) error) error Atomic(ctx context.Context, fn func(ctx context.Context, tx Manager) error) error
Users() UserRepository Users() UserRepository
Notes() NoteRepository Notes() NoteRepository
Follows() FollowRepository Follows() FollowRepository
InstanceMetadata() InstanceMetadataRepository
} }

View file

@ -2,6 +2,7 @@ package service
import ( import (
"context" "context"
"github.com/gofiber/fiber/v2"
"github.com/lysand-org/versia-go/internal/repository" "github.com/lysand-org/versia-go/internal/repository"
"github.com/google/uuid" "github.com/google/uuid"
@ -19,11 +20,16 @@ type UserService interface {
GetUserByID(ctx context.Context, id uuid.UUID) (*entity.User, error) GetUserByID(ctx context.Context, id uuid.UUID) (*entity.User, error)
GetWebfingerForUser(ctx context.Context, userID string) (*webfinger.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 { type FederationService interface {
SendToInbox(ctx context.Context, author *entity.User, target *entity.User, object any) ([]byte, error) SendToInbox(ctx context.Context, author *entity.User, target *entity.User, object any) ([]byte, error)
GetUser(ctx context.Context, uri *lysand.URL) (*lysand.User, 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 { type InboxService interface {
@ -44,6 +50,14 @@ type FollowService interface {
ImportLysandFollow(ctx context.Context, lFollow *lysand.Follow) (*entity.Follow, error) ImportLysandFollow(ctx context.Context, lFollow *lysand.Follow) (*entity.Follow, error)
} }
type InstanceMetadataService interface {
Ours(ctx context.Context) (*entity.InstanceMetadata, error)
}
type TaskService interface { type TaskService interface {
ScheduleTask(ctx context.Context, type_ string, data any) error 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) var _ service.InboxService = (*InboxServiceImpl)(nil)
type InboxServiceImpl struct { type InboxServiceImpl struct {
repositories repository.Manager
federationService service.FederationService federationService service.FederationService
repositories repository.Manager
telemetry *unitel.Telemetry telemetry *unitel.Telemetry
log logr.Logger 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{ return &InboxServiceImpl{
repositories: repositories,
federationService: federationService, federationService: federationService,
repositories: repositories,
telemetry: telemetry, telemetry: telemetry,
log: log, log: log,
} }
} }
func (i InboxServiceImpl) WithRepositories(repositories repository.Manager) service.InboxService { 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 { 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() defer s.End()
ctx = s.Context() 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 { 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() defer s.End()
ctx = s.Context() 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 { 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() defer s.End()
ctx = s.Context() ctx = s.Context()

View file

@ -1,17 +1,34 @@
package svc_impls package svc_impls
import ( import (
"bytes"
"context" "context"
"crypto/rand"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"git.devminer.xyz/devminer/unitel" "git.devminer.xyz/devminer/unitel"
"github.com/go-logr/logr" "github.com/go-logr/logr"
"github.com/lysand-org/versia-go/internal/entity" "github.com/lysand-org/versia-go/internal/entity"
"github.com/lysand-org/versia-go/internal/service" "github.com/lysand-org/versia-go/internal/service"
"github.com/lysand-org/versia-go/pkg/lysand" "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 { type FederationServiceImpl struct {
httpC *protoretry.Client
federationClient *lysand.FederationClient federationClient *lysand.FederationClient
telemetry *unitel.Telemetry telemetry *unitel.Telemetry
@ -19,38 +36,139 @@ type FederationServiceImpl struct {
log logr.Logger 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{ return &FederationServiceImpl{
httpC: protoretry.New(httpClient),
federationClient: federationClient, federationClient: federationClient,
telemetry: telemetry, telemetry: telemetry,
log: log, log: log,
} }
} }
func (i FederationServiceImpl) SendToInbox(ctx context.Context, author *entity.User, target *entity.User, object any) ([]byte, error) { func (i *FederationServiceImpl) GetUser(ctx context.Context, uri *lysand.URL) (*lysand.User, error) {
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.FederationServiceImpl.SendToInbox") s := i.telemetry.StartSpan(ctx, "function", "svc_impls/FederationServiceImpl.GetUser").
AddAttribute("userURI", uri.String())
defer s.End() defer s.End()
ctx = s.Context() 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 { if err != nil {
i.log.Error(err, "Failed to send to inbox", "author", author.ID, "target", target.ID) s.SetSimpleStatus(unitel.Error, err.Error())
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)
return nil, err 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 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) { 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("follower", follower.URI).
AddAttribute("followee", followee.URI) AddAttribute("followee", followee.URI)
defer s.End() 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) { 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) AddAttribute("followID", id)
defer s.End() defer s.End()
ctx = s.Context() 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) { 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()) AddAttribute("uri", lFollow.URI.String())
defer s.End() defer s.End()
ctx = s.Context() 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) { 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() defer s.End()
ctx = s.Context() 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) { 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() defer s.End()
ctx = s.Context() 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) { 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() defer s.End()
ctx = s.Context() 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 { 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() defer s.End()
ctx = s.Context() ctx = s.Context()

View file

@ -4,7 +4,7 @@ import (
"context" "context"
"crypto/ed25519" "crypto/ed25519"
"crypto/rand" "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/repository"
"github.com/lysand-org/versia-go/internal/service" "github.com/lysand-org/versia-go/internal/service"
"net/url" "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) { 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() defer s.End()
ctx = s.Context() 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) { 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() defer s.End()
ctx = s.Context() 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) { 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() defer s.End()
ctx = s.Context() ctx = s.Context()
@ -90,7 +90,7 @@ func (i UserServiceImpl) GetWebfingerForUser(ctx context.Context, userID string)
return nil, err return nil, err
} }
if u == nil { if u == nil {
return nil, fmt.Errorf("user not found") return nil, api_schema.ErrUserNotFound
} }
wf := &webfinger.User{ wf := &webfinger.User{
@ -120,3 +120,25 @@ func (i UserServiceImpl) GetWebfingerForUser(ctx context.Context, userID string)
return wf, nil 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 { if err != nil {
return err return err
} }
if n == nil {
t.log.V(-1).Info("Could not find note", "id", data.NoteID)
return nil
}
for _, uu := range n.Mentions { for _, uu := range n.Mentions {
if !uu.IsRemote { 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())} newPath := &url.URL{Path: fmt.Sprintf("/api/notes/%s/", uuid.String())}
return lysand.URLFromStd(config.C.PublicAddress.ResolveReference(newPath)) 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 ( import (
"errors" "errors"
"github.com/lysand-org/versia-go/ent/schema"
"github.com/lysand-org/versia-go/internal/validators" "github.com/lysand-org/versia-go/internal/validators"
"reflect" "reflect"
"regexp"
"strings" "strings"
"github.com/go-logr/logr" "github.com/go-logr/logr"
@ -11,11 +13,20 @@ import (
universal_translator "github.com/go-playground/universal-translator" universal_translator "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10" "github.com/go-playground/validator/v10"
en_translations "github.com/go-playground/validator/v10/translations/en" 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" "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 { type BodyValidatorImpl struct {
validator *validator.Validate validator *validator.Validate
@ -28,13 +39,13 @@ type BodyValidatorImpl struct {
func NewBodyValidator(log logr.Logger) *BodyValidatorImpl { func NewBodyValidator(log logr.Logger) *BodyValidatorImpl {
en := en_locale.New() en := en_locale.New()
translator := universal_translator.New(en, en) translator := universal_translator.New(en, en)
trans, ok := translator.GetTranslator("en") enTranslator, ok := translator.GetTranslator("en")
if !ok { if !ok {
panic("failed to get \"en\" translator") panic("failed to get \"en\" translator")
} }
validate := validator.New(validator.WithRequiredStructEnabled()) 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") panic("failed to register default translations")
} }
@ -46,25 +57,65 @@ func NewBodyValidator(log logr.Logger) *BodyValidatorImpl {
return name return name
}) })
if err := validate.RegisterValidation("username_regex", func(fl validator.FieldLevel) bool { 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 return schema.ValidateUsername(fl.Field().String()) == nil
}); err != nil { },
panic("failed to register username_regex validator") },
"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()))
} }
if err := validate.RegisterTranslation("username_regex", trans, func(ut universal_translator.Translator) error { return false
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()) "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
},
},
}
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 return t
}); err != nil { }
panic("failed to register user_regex translation")
if err := validate.RegisterTranslation(identifier, enTranslator, register, translate); err != nil {
log.Error(err, "failed to register validator translator", "identifier", identifier)
}
} }
return &BodyValidatorImpl{ return &BodyValidatorImpl{
validator: validate, validator: validate,
translator: translator, translator: translator,
enTranslator: trans, enTranslator: enTranslator,
log: log,
} }
} }

View file

@ -1,17 +1,15 @@
package val_impls package val_impls
import ( import (
"bytes"
"context" "context"
"errors" "errors"
"git.devminer.xyz/devminer/unitel" "git.devminer.xyz/devminer/unitel"
"github.com/go-logr/logr" "github.com/go-logr/logr"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"github.com/lysand-org/versia-go/internal/repository" "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/internal/validators"
"github.com/lysand-org/versia-go/pkg/lysand" "github.com/lysand-org/versia-go/pkg/lysand"
"github.com/valyala/fasthttp/fasthttpadaptor"
"io"
"net/http" "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 { 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() defer s.End()
ctx = s.Context() ctx = s.Context()
@ -55,13 +53,13 @@ func (i RequestValidatorImpl) Validate(ctx context.Context, r *http.Request) err
return err return err
} }
body, err := copyBody(r) body, err := utils.CopyBody(r)
if err != nil { if err != nil {
return err return err
} }
if !(lysand.Verifier{PublicKey: user.PublicKey}).Verify(r.Method, r.URL, body, fedHeaders) { if !(lysand.Verifier{PublicKey: user.PublicKey.Key}).Verify(r.Method, r.URL, body, fedHeaders) {
i.log.Info("signature verification failed", "user", user.URI, "url", r.URL.Path) i.log.WithCallDepth(1).Info("signature verification failed", "user", user.URI, "url", r.URL.Path)
s.CaptureError(ErrInvalidSignature) s.CaptureError(ErrInvalidSignature)
return 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 { 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() defer s.End()
ctx = s.Context() ctx = s.Context()
r, err := convertToStdRequest(c) r, err := utils.ConvertToStdRequest(c)
if err != nil { if err != nil {
return err return err
} }
return i.Validate(ctx, r) 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
}

122
main.go
View file

@ -4,8 +4,11 @@ import (
"context" "context"
"crypto/ed25519" "crypto/ed25519"
"crypto/rand" "crypto/rand"
"crypto/tls"
"database/sql" "database/sql"
"database/sql/driver" "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/follow_handler"
"github.com/lysand-org/versia-go/internal/handlers/meta_handler" "github.com/lysand-org/versia-go/internal/handlers/meta_handler"
"github.com/lysand-org/versia-go/internal/handlers/note_handler" "github.com/lysand-org/versia-go/internal/handlers/note_handler"
@ -27,11 +30,9 @@ import (
"github.com/go-logr/zerologr" "github.com/go-logr/zerologr"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/cors" "github.com/gofiber/fiber/v2/middleware/cors"
"github.com/google/uuid"
pgx "github.com/jackc/pgx/v5/stdlib" pgx "github.com/jackc/pgx/v5/stdlib"
"github.com/lysand-org/versia-go/config" "github.com/lysand-org/versia-go/config"
"github.com/lysand-org/versia-go/ent" "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/database"
"github.com/lysand-org/versia-go/internal/handlers/user_handler" "github.com/lysand-org/versia-go/internal/handlers/user_handler"
"github.com/lysand-org/versia-go/internal/tasks" "github.com/lysand-org/versia-go/internal/tasks"
@ -59,17 +60,23 @@ func main() {
tel, err := unitel.Initialize(config.C.Telemetry) tel, err := unitel.Initialize(config.C.Telemetry)
if err != nil { 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( Transport: tel.NewTracedTransport(
http.DefaultTransport, &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: config.C.Telemetry.Environment == "development"}},
false, // TODO: Only forward traces to configured hosts
[]string{"origin", "date", "signature"}, true,
[]string{"host", "date", "signature"}, []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") log.Debug().Msg("Opening database connection")
var db *ent.Client var db *ent.Client
@ -79,37 +86,46 @@ func main() {
db, err = openDB(tel, true, config.C.DatabaseURI) db, err = openDB(tel, true, config.C.DatabaseURI)
} }
if err != nil { 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() defer db.Close()
nc, err := nats.Connect(config.C.NATSURI) nc, err := nats.Connect(config.C.NATSURI)
if err != nil { 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") 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 { 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() defer tq.Close()
log.Debug().Msg("Running schema migration") log.Debug().Msg("Running schema migration")
if err := migrateDB(db, zerologr.New(&log.Logger).WithName("migrate-db"), tel); err != nil { 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 // 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")) taskService := svc_impls.NewTaskServiceImpl(tq, tel, zerologr.New(&log.Logger).WithName("task-service"))
// Manager // 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 { 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) return repo_impls.NewUserRepositoryImpl(federationService, db, log, telemetry)
}, repo_impls.NewNoteRepositoryImpl, repo_impls.NewFollowRepositoryImpl) },
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 // Validators
@ -121,19 +137,20 @@ func main() {
userService := svc_impls.NewUserServiceImpl(repos, federationService, tel, zerologr.New(&log.Logger).WithName("user-service")) 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")) 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")) 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 // 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")) 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")) 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 // Initialization
if err := initServerActor(db, tel); err != nil { 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{ web := fiber.New(fiber.Config{
@ -160,9 +177,9 @@ func main() {
WaitForDelivery: false, WaitForDelivery: false,
Timeout: 5 * time.Second, Timeout: 5 * time.Second,
// host for incoming requests // 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 // origin for outgoing requests
TraceResponseHeaders: []string{"origin", "date", "signature", "origin"}, TraceResponseHeaders: []string{"host", "x-nonce", "x-signature", "x-signed-by"},
// IgnoredRoutes: nil, // IgnoredRoutes: nil,
})) }))
web.Use(unitel.RequestLogger(log.Logger, true, true)) 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")). tasks.NewHandler(federationService, repos, tel, zerologr.New(&log.Logger).WithName("task-handler")).
Register(tq) 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") log.Fatal().Err(err).Msg("failed to start taskqueue client")
} }
}() }()
@ -195,7 +212,7 @@ func main() {
defer wg.Done() defer wg.Done()
log.Debug().Msg("Starting server") 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") log.Fatal().Err(err).Msg("Failed to start server")
} }
}() }()
@ -277,46 +294,45 @@ func initServerActor(db *ent.Client, telemetry *unitel.Telemetry) error {
}(tx) }(tx)
ctx = tx.Context() 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")
return err
}
if ent.IsNotFound(err) {
pub, priv, err := ed25519.GenerateKey(rand.Reader) pub, priv, err := ed25519.GenerateKey(rand.Reader)
if err != nil { if err != nil {
log.Error().Err(err).Msg("Failed to generate keypair") log.Error().Err(err).Msg("Failed to generate keypair")
return err return err
} }
uid := uuid.New() err = tx.InstanceMetadata.Create().
err = tx.User.Create().
SetID(uid).
SetUsername("actor").
SetIsRemote(false). SetIsRemote(false).
SetURI(utils.UserAPIURL(uid).String()). SetURI(utils.InstanceMetadataAPIURL().String()).
SetIndexable(false). SetName(config.C.InstanceName).
SetPrivacyLevel(user.PrivacyLevelPrivate). SetNillableDescription(config.C.InstanceDescription).
SetPublicKey(pub). SetHost(config.C.Host).
SetPrivateKey(priv). SetPrivateKey(priv).
SetInbox(utils.UserInboxAPIURL(uid).String()). SetPublicKey(pub).
SetOutbox(utils.UserOutboxAPIURL(uid).String()). SetPublicKeyAlgorithm("ed25519").
SetFeatured(utils.UserFeaturedAPIURL(uid).String()). SetSoftwareName("versia-go").
SetFollowers(utils.UserFollowersAPIURL(uid).String()). SetSoftwareVersion("0.0.1").
SetFollowing(utils.UserFollowingAPIURL(uid).String()). 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) Exec(ctx)
if err != nil { if err != nil {
log.Error().Err(err).Msg("Failed to create user") log.Error().Err(err).Msg("Failed to create server metadata")
return err return err
} }
}
tx.MarkForCommit() tx.MarkForCommit()

View file

@ -1,15 +1,7 @@
package lysand package lysand
import ( import (
"bytes"
"context"
"crypto/ed25519"
"crypto/rand"
"encoding/base64"
"encoding/json" "encoding/json"
"fmt"
"net/http"
"net/url"
) )
// User represents a user object in the Lysand protocol. For more information, see the [Spec]. // 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. // PublicKey is the public key of the user.
// https://lysand.org/objects/user#public-key // 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. // DisplayName is the display name of the user.
// https://lysand.org/objects/user#display-name // https://lysand.org/objects/user#display-name
@ -66,14 +58,6 @@ type User struct {
// https://lysand.org/objects/user#following // https://lysand.org/objects/user#following
Following *URL `json:"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. // Inbox is the inbox of the user.
// https://lysand.org/objects/user#posts // https://lysand.org/objects/user#posts
Inbox *URL `json:"inbox"` Inbox *URL `json:"inbox"`
@ -94,60 +78,3 @@ type Field struct {
Key TextContentTypeMap `json:"key"` Key TextContentTypeMap `json:"key"`
Value TextContentTypeMap `json:"value"` 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 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 { func must[In any, Out any](fn func(In) (Out, error), v In) Out {
out, err := fn(v) out, err := fn(v)
if err != nil { if err != nil {
@ -45,17 +8,3 @@ func must[In any, Out any](fn func(In) (Out, error), v In) Out {
return 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 package lysand
import ( import (
"context"
"fmt" "fmt"
"github.com/go-logr/logr" "github.com/go-logr/logr"
"io" "github.com/lysand-org/versia-go/pkg/protoretry"
"net/http" "net/http"
"net/url" "net/url"
"time" "time"
@ -22,6 +21,7 @@ func (e *ResponseError) Error() string {
type FederationClient struct { type FederationClient struct {
log logr.Logger log logr.Logger
httpC *http.Client httpC *http.Client
hc *protoretry.Client
} }
type Opt func(c *FederationClient) 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", useragent: "github.com/lysand-org/versia-go/pkg/lysand#0.0.1",
} }
c.hc = protoretry.New(c.httpC)
return c 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 { type federationClientHTTPTransport struct {
inner http.RoundTripper inner http.RoundTripper
useragent string useragent string

View file

@ -25,6 +25,14 @@ func (f *FederationHeaders) Inject(h http.Header) {
h.Set("x-signature", base64.StdEncoding.EncodeToString(f.Signature)) 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) { func ExtractFederationHeaders(h http.Header) (*FederationHeaders, error) {
signedBy := h.Get("x-signed-by") signedBy := h.Get("x-signed-by")
if signedBy == "" { if signedBy == "" {
@ -41,14 +49,19 @@ func ExtractFederationHeaders(h http.Header) (*FederationHeaders, error) {
return nil, fmt.Errorf("missing x-nonce header") return nil, fmt.Errorf("missing x-nonce header")
} }
signature := h.Get("x-signature") rawSignature := h.Get("x-signature")
if signature == "" { if rawSignature == "" {
return nil, fmt.Errorf("missing x-signature header") return nil, fmt.Errorf("missing x-signature header")
} }
signature, err := base64.StdEncoding.DecodeString(rawSignature)
if err != nil {
return nil, err
}
return &FederationHeaders{ return &FederationHeaders{
SignedBy: u, SignedBy: u,
Nonce: nonce, Nonce: nonce,
Signature: []byte(signature), Signature: signature,
}, nil }, 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 package lysand
import ( import (
"crypto"
"crypto/ed25519" "crypto/ed25519"
"encoding/base64" "encoding/base64"
"fmt" "fmt"
versiacrypto "github.com/lysand-org/versia-go/pkg/lysand/crypto"
"net/url" "net/url"
"os"
"strings" "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)) 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 { func (s *SignatureData) Validate(pubKey crypto.PublicKey, signature []byte) bool {
return ed25519.Verify(pubKey, []byte(s.String()), signature) 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 { func (s *SignatureData) Sign(privKey ed25519.PrivateKey) []byte {
@ -54,11 +65,10 @@ func (s Signer) Sign(signatureData SignatureData) *FederationHeaders {
} }
type Verifier struct { type Verifier struct {
PublicKey ed25519.PublicKey PublicKey crypto.PublicKey
} }
func (v Verifier) Verify(method string, u *url.URL, body []byte, fedHeaders *FederationHeaders) bool { func (v Verifier) Verify(method string, u *url.URL, body []byte, fedHeaders *FederationHeaders) bool {
sigData := NewSignatureData(method, fedHeaders.Nonce, u, hashSHA256(body)) return NewSignatureData(method, fedHeaders.Nonce, u, versiacrypto.SHA256(body)).
Validate(v.PublicKey, fedHeaders.Signature)
return sigData.Validate(v.PublicKey, fedHeaders.Signature)
} }

View file

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

View file

@ -12,20 +12,20 @@ import (
func TestSPKIPublicKey_UnmarshalJSON(t *testing.T) { func TestSPKIPublicKey_UnmarshalJSON(t *testing.T) {
expectedPk := must(x509.ParsePKIXPublicKey, must(base64.StdEncoding.DecodeString, "MCowBQYDK2VwAyEAgKNt+9eyOXdb7MSrrmHlsFD2H9NGwC+56PjpWD46Tcs=")) expectedPk := must(x509.ParsePKIXPublicKey, must(base64.StdEncoding.DecodeString, "MCowBQYDK2VwAyEAgKNt+9eyOXdb7MSrrmHlsFD2H9NGwC+56PjpWD46Tcs="))
pk := PublicKey{} pk := UserPublicKey{}
raw := []byte(`{"public_key":"MCowBQYDK2VwAyEAgKNt+9eyOXdb7MSrrmHlsFD2H9NGwC+56PjpWD46Tcs="}`) raw := []byte(`{"public_key":"MCowBQYDK2VwAyEAgKNt+9eyOXdb7MSrrmHlsFD2H9NGwC+56PjpWD46Tcs="}`)
if err := json.Unmarshal(raw, &pk); err != nil { if err := json.Unmarshal(raw, &pk); err != nil {
t.Error(err) 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) { func TestSPKIPublicKey_MarshalJSON(t *testing.T) {
expectedPk := must(x509.ParsePKIXPublicKey, must(base64.StdEncoding.DecodeString, "MCowBQYDK2VwAyEAgKNt+9eyOXdb7MSrrmHlsFD2H9NGwC+56PjpWD46Tcs=")).(ed25519.PublicKey) expectedPk := must(x509.ParsePKIXPublicKey, must(base64.StdEncoding.DecodeString, "MCowBQYDK2VwAyEAgKNt+9eyOXdb7MSrrmHlsFD2H9NGwC+56PjpWD46Tcs=")).(ed25519.PublicKey)
pk := PublicKey{ pk := UserPublicKey{
PublicKey: SPKIPublicKey(expectedPk), Key: SPKIPublicKey(expectedPk),
} }
if _, err := json.Marshal(pk); err != nil { if _, err := json.Marshal(pk); err != nil {
t.Error(err) 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 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) js, err := jetstream.New(natsClient)
if err != nil { if err != nil {
return nil, err return nil, err
} }
s, err := js.CreateStream(ctx, jetstream.StreamConfig{ s, err := js.CreateStream(ctx, jetstream.StreamConfig{
Name: name, Name: streamName,
Subjects: []string{name + ".*"}, Subjects: []string{streamName + ".*"},
MaxConsumers: -1, MaxConsumers: -1,
MaxMsgs: -1, MaxMsgs: -1,
Discard: jetstream.DiscardOld, Discard: jetstream.DiscardOld,
@ -89,7 +89,7 @@ func NewClient(ctx context.Context, name string, natsClient *nats.Conn, telemetr
AllowDirect: true, AllowDirect: true,
}) })
if errors.Is(err, nats.ErrStreamNameAlreadyInUse) { if errors.Is(err, nats.ErrStreamNameAlreadyInUse) {
s, err = js.Stream(ctx, name) s, err = js.Stream(ctx, streamName)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -100,8 +100,8 @@ func NewClient(ctx context.Context, name string, natsClient *nats.Conn, telemetr
stopCh := make(chan struct{}) stopCh := make(chan struct{})
c := &Client{ c := &Client{
name: name, name: streamName,
subject: name + ".tasks", subject: streamName + ".tasks",
handlers: map[string][]Handler{}, handlers: map[string][]Handler{},
@ -145,7 +145,7 @@ func (c *Client) Submit(ctx context.Context, task Task) error {
if err != nil { if err != nil {
return err 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) 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) { 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 { if _, ok := c.handlers[type_]; !ok {
c.handlers[type_] = []Handler{} c.handlers[type_] = []Handler{}
@ -161,13 +161,11 @@ func (c *Client) RegisterHandler(type_ string, handler Handler) {
c.handlers[type_] = append(c.handlers[type_], handler) c.handlers[type_] = append(c.handlers[type_], handler)
} }
func (c *Client) Start(ctx context.Context) error { func (c *Client) StartConsumer(ctx context.Context, consumerGroup string) error {
c.log.Info("starting") c.log.Info("Starting consumer")
sub, err := c.js.CreateConsumer(ctx, c.name, jetstream.ConsumerConfig{ sub, err := c.js.CreateConsumer(ctx, c.name, jetstream.ConsumerConfig{
// TODO: set name properly Durable: consumerGroup,
Name: "versia-go",
Durable: "versia-go",
DeliverPolicy: jetstream.DeliverAllPolicy, DeliverPolicy: jetstream.DeliverAllPolicy,
ReplayPolicy: jetstream.ReplayInstantPolicy, ReplayPolicy: jetstream.ReplayInstantPolicy,
AckPolicy: jetstream.AckExplicitPolicy, AckPolicy: jetstream.AckExplicitPolicy,
@ -191,16 +189,16 @@ func (c *Client) Start(ctx context.Context) error {
msg, err := m.Next() msg, err := m.Next()
if err != nil { if err != nil {
if errors.Is(err, jetstream.ErrMsgIteratorClosed) { if errors.Is(err, jetstream.ErrMsgIteratorClosed) {
c.log.Info("stopping") c.log.Info("Stopping")
return return
} }
c.log.Error(err, "failed to get next message") c.log.Error(err, "Failed to get next message")
break break
} }
if err := c.handleTask(ctx, msg); err != nil { 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 break
} }
} }
@ -224,7 +222,7 @@ func (c *Client) handleTask(ctx context.Context, msg jetstream.Msg) error {
var w taskWrapper var w taskWrapper
if err := json.Unmarshal(data, &w); err != nil { if err := json.Unmarshal(data, &w); err != nil {
if err := msg.Nak(); 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 return err
@ -246,21 +244,21 @@ func (c *Client) handleTask(ctx context.Context, msg jetstream.Msg) error {
handlers, ok := c.handlers[w.Task.Type] handlers, ok := c.handlers[w.Task.Type]
if !ok { 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() return msg.Nak()
} }
var errs CombinedError var errs CombinedError
for _, handler := range handlers { for _, handler := range handlers {
if err := handler(ctx, w.Task); err != nil { 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) errs.Errors = append(errs.Errors, err)
} }
} }
if len(errs.Errors) > 0 { if len(errs.Errors) > 0 {
if err := msg.Nak(); err != nil { 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) errs.Errors = append(errs.Errors, err)
} }

View file

@ -1,13 +1,19 @@
package webfinger package webfinger
import ( import (
"context"
"encoding/json"
"errors" "errors"
"fmt"
"github.com/lysand-org/versia-go/pkg/protoretry"
"net/http"
"net/url" "net/url"
"strings" "strings"
) )
var ( var (
ErrInvalidSyntax = errors.New("must follow the format \"acct:<ID|Username>@<DOMAIN>\"") 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) { func ParseResource(res string) (*UserID, error) {
@ -48,7 +54,7 @@ type Response struct {
type Link struct { type Link struct {
Relation string `json:"rel"` Relation string `json:"rel"`
Type any `json:"type"` Type string `json:"type"`
Link string `json:"href"` 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
}