- Read handler for create activities (notes only so far) - Read handler for note objects - Structure laid out for other objects, activities and collections - DB structure for activities created - Update access logging TODO: Create collections type in DB to describe a collection group
This commit is contained in:
parent
cfa0566c6d
commit
12c9e17c4b
24 changed files with 1327 additions and 206 deletions
7
go.mod
7
go.mod
|
@ -1,12 +1,10 @@
|
|||
module git.mstar.dev/mstar/linstrom
|
||||
|
||||
go 1.23.0
|
||||
|
||||
toolchain go1.23.7
|
||||
go 1.24.2
|
||||
|
||||
require (
|
||||
git.mstar.dev/mstar/canvas v0.13.1
|
||||
git.mstar.dev/mstar/goutils v1.13.0
|
||||
git.mstar.dev/mstar/goutils v1.14.0
|
||||
github.com/BurntSushi/toml v1.5.0
|
||||
github.com/dgraph-io/ristretto v0.2.0
|
||||
github.com/eko/gocache/lib/v4 v4.2.0
|
||||
|
@ -38,6 +36,7 @@ require (
|
|||
|
||||
require (
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
git.mstar.dev/mstar/treeificator v0.0.0-20250423153311-dc24f39ca3c9 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
|
|
4
go.sum
4
go.sum
|
@ -39,6 +39,10 @@ git.mstar.dev/mstar/goutils v1.12.3 h1:Wx7i8/a99Cp+Y/XcXgqQr0r9cSsJu7QkWBlKyprTH
|
|||
git.mstar.dev/mstar/goutils v1.12.3/go.mod h1:juxY0eZEMnA95fedRp2LVXvUBgEjz66nE8SEdGKcxMA=
|
||||
git.mstar.dev/mstar/goutils v1.13.0 h1:j2AA3izqTumZyUgC2wi/JdIZAtnDQLve2iexI5kWMgM=
|
||||
git.mstar.dev/mstar/goutils v1.13.0/go.mod h1:juxY0eZEMnA95fedRp2LVXvUBgEjz66nE8SEdGKcxMA=
|
||||
git.mstar.dev/mstar/goutils v1.14.0 h1:XxhP528dwyaDnnVX3Si3UF3bQgNGZQOQxNTGD86mlEo=
|
||||
git.mstar.dev/mstar/goutils v1.14.0/go.mod h1:juxY0eZEMnA95fedRp2LVXvUBgEjz66nE8SEdGKcxMA=
|
||||
git.mstar.dev/mstar/treeificator v0.0.0-20250423153311-dc24f39ca3c9 h1:XXfafmvV6B0Yl6ucec0Gy+VgwWRI+tzLMSyuOgRpXDw=
|
||||
git.mstar.dev/mstar/treeificator v0.0.0-20250423153311-dc24f39ca3c9/go.mod h1:7wp7WyRRR5gUSur0Ur7RheG1io2QdVoxJPRIrN3pxqo=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
|
||||
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
|
|
394
storage-new/dbgen/activitystreams_activities.gen.go
Normal file
394
storage-new/dbgen/activitystreams_activities.gen.go
Normal file
|
@ -0,0 +1,394 @@
|
|||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package dbgen
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"git.mstar.dev/mstar/linstrom/storage-new/models"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
"gorm.io/gorm/schema"
|
||||
|
||||
"gorm.io/gen"
|
||||
"gorm.io/gen/field"
|
||||
|
||||
"gorm.io/plugin/dbresolver"
|
||||
)
|
||||
|
||||
func newActivitystreamsActivity(db *gorm.DB, opts ...gen.DOOption) activitystreamsActivity {
|
||||
_activitystreamsActivity := activitystreamsActivity{}
|
||||
|
||||
_activitystreamsActivity.activitystreamsActivityDo.UseDB(db, opts...)
|
||||
_activitystreamsActivity.activitystreamsActivityDo.UseModel(&models.ActivitystreamsActivity{})
|
||||
|
||||
tableName := _activitystreamsActivity.activitystreamsActivityDo.TableName()
|
||||
_activitystreamsActivity.ALL = field.NewAsterisk(tableName)
|
||||
_activitystreamsActivity.Id = field.NewString(tableName, "id")
|
||||
_activitystreamsActivity.Type = field.NewString(tableName, "type")
|
||||
_activitystreamsActivity.ObjectId = field.NewString(tableName, "object_id")
|
||||
_activitystreamsActivity.ObjectType = field.NewUint32(tableName, "object_type")
|
||||
|
||||
_activitystreamsActivity.fillFieldMap()
|
||||
|
||||
return _activitystreamsActivity
|
||||
}
|
||||
|
||||
type activitystreamsActivity struct {
|
||||
activitystreamsActivityDo
|
||||
|
||||
ALL field.Asterisk
|
||||
Id field.String
|
||||
Type field.String
|
||||
ObjectId field.String
|
||||
ObjectType field.Uint32
|
||||
|
||||
fieldMap map[string]field.Expr
|
||||
}
|
||||
|
||||
func (a activitystreamsActivity) Table(newTableName string) *activitystreamsActivity {
|
||||
a.activitystreamsActivityDo.UseTable(newTableName)
|
||||
return a.updateTableName(newTableName)
|
||||
}
|
||||
|
||||
func (a activitystreamsActivity) As(alias string) *activitystreamsActivity {
|
||||
a.activitystreamsActivityDo.DO = *(a.activitystreamsActivityDo.As(alias).(*gen.DO))
|
||||
return a.updateTableName(alias)
|
||||
}
|
||||
|
||||
func (a *activitystreamsActivity) updateTableName(table string) *activitystreamsActivity {
|
||||
a.ALL = field.NewAsterisk(table)
|
||||
a.Id = field.NewString(table, "id")
|
||||
a.Type = field.NewString(table, "type")
|
||||
a.ObjectId = field.NewString(table, "object_id")
|
||||
a.ObjectType = field.NewUint32(table, "object_type")
|
||||
|
||||
a.fillFieldMap()
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
func (a *activitystreamsActivity) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
|
||||
_f, ok := a.fieldMap[fieldName]
|
||||
if !ok || _f == nil {
|
||||
return nil, false
|
||||
}
|
||||
_oe, ok := _f.(field.OrderExpr)
|
||||
return _oe, ok
|
||||
}
|
||||
|
||||
func (a *activitystreamsActivity) fillFieldMap() {
|
||||
a.fieldMap = make(map[string]field.Expr, 4)
|
||||
a.fieldMap["id"] = a.Id
|
||||
a.fieldMap["type"] = a.Type
|
||||
a.fieldMap["object_id"] = a.ObjectId
|
||||
a.fieldMap["object_type"] = a.ObjectType
|
||||
}
|
||||
|
||||
func (a activitystreamsActivity) clone(db *gorm.DB) activitystreamsActivity {
|
||||
a.activitystreamsActivityDo.ReplaceConnPool(db.Statement.ConnPool)
|
||||
return a
|
||||
}
|
||||
|
||||
func (a activitystreamsActivity) replaceDB(db *gorm.DB) activitystreamsActivity {
|
||||
a.activitystreamsActivityDo.ReplaceDB(db)
|
||||
return a
|
||||
}
|
||||
|
||||
type activitystreamsActivityDo struct{ gen.DO }
|
||||
|
||||
type IActivitystreamsActivityDo interface {
|
||||
gen.SubQuery
|
||||
Debug() IActivitystreamsActivityDo
|
||||
WithContext(ctx context.Context) IActivitystreamsActivityDo
|
||||
WithResult(fc func(tx gen.Dao)) gen.ResultInfo
|
||||
ReplaceDB(db *gorm.DB)
|
||||
ReadDB() IActivitystreamsActivityDo
|
||||
WriteDB() IActivitystreamsActivityDo
|
||||
As(alias string) gen.Dao
|
||||
Session(config *gorm.Session) IActivitystreamsActivityDo
|
||||
Columns(cols ...field.Expr) gen.Columns
|
||||
Clauses(conds ...clause.Expression) IActivitystreamsActivityDo
|
||||
Not(conds ...gen.Condition) IActivitystreamsActivityDo
|
||||
Or(conds ...gen.Condition) IActivitystreamsActivityDo
|
||||
Select(conds ...field.Expr) IActivitystreamsActivityDo
|
||||
Where(conds ...gen.Condition) IActivitystreamsActivityDo
|
||||
Order(conds ...field.Expr) IActivitystreamsActivityDo
|
||||
Distinct(cols ...field.Expr) IActivitystreamsActivityDo
|
||||
Omit(cols ...field.Expr) IActivitystreamsActivityDo
|
||||
Join(table schema.Tabler, on ...field.Expr) IActivitystreamsActivityDo
|
||||
LeftJoin(table schema.Tabler, on ...field.Expr) IActivitystreamsActivityDo
|
||||
RightJoin(table schema.Tabler, on ...field.Expr) IActivitystreamsActivityDo
|
||||
Group(cols ...field.Expr) IActivitystreamsActivityDo
|
||||
Having(conds ...gen.Condition) IActivitystreamsActivityDo
|
||||
Limit(limit int) IActivitystreamsActivityDo
|
||||
Offset(offset int) IActivitystreamsActivityDo
|
||||
Count() (count int64, err error)
|
||||
Scopes(funcs ...func(gen.Dao) gen.Dao) IActivitystreamsActivityDo
|
||||
Unscoped() IActivitystreamsActivityDo
|
||||
Create(values ...*models.ActivitystreamsActivity) error
|
||||
CreateInBatches(values []*models.ActivitystreamsActivity, batchSize int) error
|
||||
Save(values ...*models.ActivitystreamsActivity) error
|
||||
First() (*models.ActivitystreamsActivity, error)
|
||||
Take() (*models.ActivitystreamsActivity, error)
|
||||
Last() (*models.ActivitystreamsActivity, error)
|
||||
Find() ([]*models.ActivitystreamsActivity, error)
|
||||
FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*models.ActivitystreamsActivity, err error)
|
||||
FindInBatches(result *[]*models.ActivitystreamsActivity, batchSize int, fc func(tx gen.Dao, batch int) error) error
|
||||
Pluck(column field.Expr, dest interface{}) error
|
||||
Delete(...*models.ActivitystreamsActivity) (info gen.ResultInfo, err error)
|
||||
Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
|
||||
UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
|
||||
Updates(value interface{}) (info gen.ResultInfo, err error)
|
||||
UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
|
||||
UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
|
||||
UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
|
||||
UpdateFrom(q gen.SubQuery) gen.Dao
|
||||
Attrs(attrs ...field.AssignExpr) IActivitystreamsActivityDo
|
||||
Assign(attrs ...field.AssignExpr) IActivitystreamsActivityDo
|
||||
Joins(fields ...field.RelationField) IActivitystreamsActivityDo
|
||||
Preload(fields ...field.RelationField) IActivitystreamsActivityDo
|
||||
FirstOrInit() (*models.ActivitystreamsActivity, error)
|
||||
FirstOrCreate() (*models.ActivitystreamsActivity, error)
|
||||
FindByPage(offset int, limit int) (result []*models.ActivitystreamsActivity, count int64, err error)
|
||||
ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
|
||||
Rows() (*sql.Rows, error)
|
||||
Row() *sql.Row
|
||||
Scan(result interface{}) (err error)
|
||||
Returning(value interface{}, columns ...string) IActivitystreamsActivityDo
|
||||
UnderlyingDB() *gorm.DB
|
||||
schema.Tabler
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) Debug() IActivitystreamsActivityDo {
|
||||
return a.withDO(a.DO.Debug())
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) WithContext(ctx context.Context) IActivitystreamsActivityDo {
|
||||
return a.withDO(a.DO.WithContext(ctx))
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) ReadDB() IActivitystreamsActivityDo {
|
||||
return a.Clauses(dbresolver.Read)
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) WriteDB() IActivitystreamsActivityDo {
|
||||
return a.Clauses(dbresolver.Write)
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) Session(config *gorm.Session) IActivitystreamsActivityDo {
|
||||
return a.withDO(a.DO.Session(config))
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) Clauses(conds ...clause.Expression) IActivitystreamsActivityDo {
|
||||
return a.withDO(a.DO.Clauses(conds...))
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) Returning(value interface{}, columns ...string) IActivitystreamsActivityDo {
|
||||
return a.withDO(a.DO.Returning(value, columns...))
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) Not(conds ...gen.Condition) IActivitystreamsActivityDo {
|
||||
return a.withDO(a.DO.Not(conds...))
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) Or(conds ...gen.Condition) IActivitystreamsActivityDo {
|
||||
return a.withDO(a.DO.Or(conds...))
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) Select(conds ...field.Expr) IActivitystreamsActivityDo {
|
||||
return a.withDO(a.DO.Select(conds...))
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) Where(conds ...gen.Condition) IActivitystreamsActivityDo {
|
||||
return a.withDO(a.DO.Where(conds...))
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) Order(conds ...field.Expr) IActivitystreamsActivityDo {
|
||||
return a.withDO(a.DO.Order(conds...))
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) Distinct(cols ...field.Expr) IActivitystreamsActivityDo {
|
||||
return a.withDO(a.DO.Distinct(cols...))
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) Omit(cols ...field.Expr) IActivitystreamsActivityDo {
|
||||
return a.withDO(a.DO.Omit(cols...))
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) Join(table schema.Tabler, on ...field.Expr) IActivitystreamsActivityDo {
|
||||
return a.withDO(a.DO.Join(table, on...))
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) LeftJoin(table schema.Tabler, on ...field.Expr) IActivitystreamsActivityDo {
|
||||
return a.withDO(a.DO.LeftJoin(table, on...))
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) RightJoin(table schema.Tabler, on ...field.Expr) IActivitystreamsActivityDo {
|
||||
return a.withDO(a.DO.RightJoin(table, on...))
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) Group(cols ...field.Expr) IActivitystreamsActivityDo {
|
||||
return a.withDO(a.DO.Group(cols...))
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) Having(conds ...gen.Condition) IActivitystreamsActivityDo {
|
||||
return a.withDO(a.DO.Having(conds...))
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) Limit(limit int) IActivitystreamsActivityDo {
|
||||
return a.withDO(a.DO.Limit(limit))
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) Offset(offset int) IActivitystreamsActivityDo {
|
||||
return a.withDO(a.DO.Offset(offset))
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IActivitystreamsActivityDo {
|
||||
return a.withDO(a.DO.Scopes(funcs...))
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) Unscoped() IActivitystreamsActivityDo {
|
||||
return a.withDO(a.DO.Unscoped())
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) Create(values ...*models.ActivitystreamsActivity) error {
|
||||
if len(values) == 0 {
|
||||
return nil
|
||||
}
|
||||
return a.DO.Create(values)
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) CreateInBatches(values []*models.ActivitystreamsActivity, batchSize int) error {
|
||||
return a.DO.CreateInBatches(values, batchSize)
|
||||
}
|
||||
|
||||
// Save : !!! underlying implementation is different with GORM
|
||||
// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
|
||||
func (a activitystreamsActivityDo) Save(values ...*models.ActivitystreamsActivity) error {
|
||||
if len(values) == 0 {
|
||||
return nil
|
||||
}
|
||||
return a.DO.Save(values)
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) First() (*models.ActivitystreamsActivity, error) {
|
||||
if result, err := a.DO.First(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*models.ActivitystreamsActivity), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) Take() (*models.ActivitystreamsActivity, error) {
|
||||
if result, err := a.DO.Take(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*models.ActivitystreamsActivity), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) Last() (*models.ActivitystreamsActivity, error) {
|
||||
if result, err := a.DO.Last(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*models.ActivitystreamsActivity), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) Find() ([]*models.ActivitystreamsActivity, error) {
|
||||
result, err := a.DO.Find()
|
||||
return result.([]*models.ActivitystreamsActivity), err
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*models.ActivitystreamsActivity, err error) {
|
||||
buf := make([]*models.ActivitystreamsActivity, 0, batchSize)
|
||||
err = a.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
|
||||
defer func() { results = append(results, buf...) }()
|
||||
return fc(tx, batch)
|
||||
})
|
||||
return results, err
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) FindInBatches(result *[]*models.ActivitystreamsActivity, batchSize int, fc func(tx gen.Dao, batch int) error) error {
|
||||
return a.DO.FindInBatches(result, batchSize, fc)
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) Attrs(attrs ...field.AssignExpr) IActivitystreamsActivityDo {
|
||||
return a.withDO(a.DO.Attrs(attrs...))
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) Assign(attrs ...field.AssignExpr) IActivitystreamsActivityDo {
|
||||
return a.withDO(a.DO.Assign(attrs...))
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) Joins(fields ...field.RelationField) IActivitystreamsActivityDo {
|
||||
for _, _f := range fields {
|
||||
a = *a.withDO(a.DO.Joins(_f))
|
||||
}
|
||||
return &a
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) Preload(fields ...field.RelationField) IActivitystreamsActivityDo {
|
||||
for _, _f := range fields {
|
||||
a = *a.withDO(a.DO.Preload(_f))
|
||||
}
|
||||
return &a
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) FirstOrInit() (*models.ActivitystreamsActivity, error) {
|
||||
if result, err := a.DO.FirstOrInit(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*models.ActivitystreamsActivity), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) FirstOrCreate() (*models.ActivitystreamsActivity, error) {
|
||||
if result, err := a.DO.FirstOrCreate(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*models.ActivitystreamsActivity), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) FindByPage(offset int, limit int) (result []*models.ActivitystreamsActivity, count int64, err error) {
|
||||
result, err = a.Offset(offset).Limit(limit).Find()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if size := len(result); 0 < limit && 0 < size && size < limit {
|
||||
count = int64(size + offset)
|
||||
return
|
||||
}
|
||||
|
||||
count, err = a.Offset(-1).Limit(-1).Count()
|
||||
return
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
|
||||
count, err = a.Count()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = a.Offset(offset).Limit(limit).Scan(result)
|
||||
return
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) Scan(result interface{}) (err error) {
|
||||
return a.DO.Scan(result)
|
||||
}
|
||||
|
||||
func (a activitystreamsActivityDo) Delete(models ...*models.ActivitystreamsActivity) (result gen.ResultInfo, err error) {
|
||||
return a.DO.Delete(models)
|
||||
}
|
||||
|
||||
func (a *activitystreamsActivityDo) withDO(do gen.Dao) *activitystreamsActivityDo {
|
||||
a.DO = *do.(*gen.DO)
|
||||
return a
|
||||
}
|
390
storage-new/dbgen/collections.gen.go
Normal file
390
storage-new/dbgen/collections.gen.go
Normal file
|
@ -0,0 +1,390 @@
|
|||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package dbgen
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"git.mstar.dev/mstar/linstrom/storage-new/models"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
"gorm.io/gorm/schema"
|
||||
|
||||
"gorm.io/gen"
|
||||
"gorm.io/gen/field"
|
||||
|
||||
"gorm.io/plugin/dbresolver"
|
||||
)
|
||||
|
||||
func newCollection(db *gorm.DB, opts ...gen.DOOption) collection {
|
||||
_collection := collection{}
|
||||
|
||||
_collection.collectionDo.UseDB(db, opts...)
|
||||
_collection.collectionDo.UseModel(&models.Collection{})
|
||||
|
||||
tableName := _collection.collectionDo.TableName()
|
||||
_collection.ALL = field.NewAsterisk(tableName)
|
||||
_collection.Id = field.NewString(tableName, "id")
|
||||
_collection.TargetId = field.NewString(tableName, "target_id")
|
||||
_collection.TargetType = field.NewUint32(tableName, "target_type")
|
||||
|
||||
_collection.fillFieldMap()
|
||||
|
||||
return _collection
|
||||
}
|
||||
|
||||
type collection struct {
|
||||
collectionDo
|
||||
|
||||
ALL field.Asterisk
|
||||
Id field.String
|
||||
TargetId field.String
|
||||
TargetType field.Uint32
|
||||
|
||||
fieldMap map[string]field.Expr
|
||||
}
|
||||
|
||||
func (c collection) Table(newTableName string) *collection {
|
||||
c.collectionDo.UseTable(newTableName)
|
||||
return c.updateTableName(newTableName)
|
||||
}
|
||||
|
||||
func (c collection) As(alias string) *collection {
|
||||
c.collectionDo.DO = *(c.collectionDo.As(alias).(*gen.DO))
|
||||
return c.updateTableName(alias)
|
||||
}
|
||||
|
||||
func (c *collection) updateTableName(table string) *collection {
|
||||
c.ALL = field.NewAsterisk(table)
|
||||
c.Id = field.NewString(table, "id")
|
||||
c.TargetId = field.NewString(table, "target_id")
|
||||
c.TargetType = field.NewUint32(table, "target_type")
|
||||
|
||||
c.fillFieldMap()
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *collection) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
|
||||
_f, ok := c.fieldMap[fieldName]
|
||||
if !ok || _f == nil {
|
||||
return nil, false
|
||||
}
|
||||
_oe, ok := _f.(field.OrderExpr)
|
||||
return _oe, ok
|
||||
}
|
||||
|
||||
func (c *collection) fillFieldMap() {
|
||||
c.fieldMap = make(map[string]field.Expr, 3)
|
||||
c.fieldMap["id"] = c.Id
|
||||
c.fieldMap["target_id"] = c.TargetId
|
||||
c.fieldMap["target_type"] = c.TargetType
|
||||
}
|
||||
|
||||
func (c collection) clone(db *gorm.DB) collection {
|
||||
c.collectionDo.ReplaceConnPool(db.Statement.ConnPool)
|
||||
return c
|
||||
}
|
||||
|
||||
func (c collection) replaceDB(db *gorm.DB) collection {
|
||||
c.collectionDo.ReplaceDB(db)
|
||||
return c
|
||||
}
|
||||
|
||||
type collectionDo struct{ gen.DO }
|
||||
|
||||
type ICollectionDo interface {
|
||||
gen.SubQuery
|
||||
Debug() ICollectionDo
|
||||
WithContext(ctx context.Context) ICollectionDo
|
||||
WithResult(fc func(tx gen.Dao)) gen.ResultInfo
|
||||
ReplaceDB(db *gorm.DB)
|
||||
ReadDB() ICollectionDo
|
||||
WriteDB() ICollectionDo
|
||||
As(alias string) gen.Dao
|
||||
Session(config *gorm.Session) ICollectionDo
|
||||
Columns(cols ...field.Expr) gen.Columns
|
||||
Clauses(conds ...clause.Expression) ICollectionDo
|
||||
Not(conds ...gen.Condition) ICollectionDo
|
||||
Or(conds ...gen.Condition) ICollectionDo
|
||||
Select(conds ...field.Expr) ICollectionDo
|
||||
Where(conds ...gen.Condition) ICollectionDo
|
||||
Order(conds ...field.Expr) ICollectionDo
|
||||
Distinct(cols ...field.Expr) ICollectionDo
|
||||
Omit(cols ...field.Expr) ICollectionDo
|
||||
Join(table schema.Tabler, on ...field.Expr) ICollectionDo
|
||||
LeftJoin(table schema.Tabler, on ...field.Expr) ICollectionDo
|
||||
RightJoin(table schema.Tabler, on ...field.Expr) ICollectionDo
|
||||
Group(cols ...field.Expr) ICollectionDo
|
||||
Having(conds ...gen.Condition) ICollectionDo
|
||||
Limit(limit int) ICollectionDo
|
||||
Offset(offset int) ICollectionDo
|
||||
Count() (count int64, err error)
|
||||
Scopes(funcs ...func(gen.Dao) gen.Dao) ICollectionDo
|
||||
Unscoped() ICollectionDo
|
||||
Create(values ...*models.Collection) error
|
||||
CreateInBatches(values []*models.Collection, batchSize int) error
|
||||
Save(values ...*models.Collection) error
|
||||
First() (*models.Collection, error)
|
||||
Take() (*models.Collection, error)
|
||||
Last() (*models.Collection, error)
|
||||
Find() ([]*models.Collection, error)
|
||||
FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*models.Collection, err error)
|
||||
FindInBatches(result *[]*models.Collection, batchSize int, fc func(tx gen.Dao, batch int) error) error
|
||||
Pluck(column field.Expr, dest interface{}) error
|
||||
Delete(...*models.Collection) (info gen.ResultInfo, err error)
|
||||
Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
|
||||
UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
|
||||
Updates(value interface{}) (info gen.ResultInfo, err error)
|
||||
UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
|
||||
UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
|
||||
UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
|
||||
UpdateFrom(q gen.SubQuery) gen.Dao
|
||||
Attrs(attrs ...field.AssignExpr) ICollectionDo
|
||||
Assign(attrs ...field.AssignExpr) ICollectionDo
|
||||
Joins(fields ...field.RelationField) ICollectionDo
|
||||
Preload(fields ...field.RelationField) ICollectionDo
|
||||
FirstOrInit() (*models.Collection, error)
|
||||
FirstOrCreate() (*models.Collection, error)
|
||||
FindByPage(offset int, limit int) (result []*models.Collection, count int64, err error)
|
||||
ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
|
||||
Rows() (*sql.Rows, error)
|
||||
Row() *sql.Row
|
||||
Scan(result interface{}) (err error)
|
||||
Returning(value interface{}, columns ...string) ICollectionDo
|
||||
UnderlyingDB() *gorm.DB
|
||||
schema.Tabler
|
||||
}
|
||||
|
||||
func (c collectionDo) Debug() ICollectionDo {
|
||||
return c.withDO(c.DO.Debug())
|
||||
}
|
||||
|
||||
func (c collectionDo) WithContext(ctx context.Context) ICollectionDo {
|
||||
return c.withDO(c.DO.WithContext(ctx))
|
||||
}
|
||||
|
||||
func (c collectionDo) ReadDB() ICollectionDo {
|
||||
return c.Clauses(dbresolver.Read)
|
||||
}
|
||||
|
||||
func (c collectionDo) WriteDB() ICollectionDo {
|
||||
return c.Clauses(dbresolver.Write)
|
||||
}
|
||||
|
||||
func (c collectionDo) Session(config *gorm.Session) ICollectionDo {
|
||||
return c.withDO(c.DO.Session(config))
|
||||
}
|
||||
|
||||
func (c collectionDo) Clauses(conds ...clause.Expression) ICollectionDo {
|
||||
return c.withDO(c.DO.Clauses(conds...))
|
||||
}
|
||||
|
||||
func (c collectionDo) Returning(value interface{}, columns ...string) ICollectionDo {
|
||||
return c.withDO(c.DO.Returning(value, columns...))
|
||||
}
|
||||
|
||||
func (c collectionDo) Not(conds ...gen.Condition) ICollectionDo {
|
||||
return c.withDO(c.DO.Not(conds...))
|
||||
}
|
||||
|
||||
func (c collectionDo) Or(conds ...gen.Condition) ICollectionDo {
|
||||
return c.withDO(c.DO.Or(conds...))
|
||||
}
|
||||
|
||||
func (c collectionDo) Select(conds ...field.Expr) ICollectionDo {
|
||||
return c.withDO(c.DO.Select(conds...))
|
||||
}
|
||||
|
||||
func (c collectionDo) Where(conds ...gen.Condition) ICollectionDo {
|
||||
return c.withDO(c.DO.Where(conds...))
|
||||
}
|
||||
|
||||
func (c collectionDo) Order(conds ...field.Expr) ICollectionDo {
|
||||
return c.withDO(c.DO.Order(conds...))
|
||||
}
|
||||
|
||||
func (c collectionDo) Distinct(cols ...field.Expr) ICollectionDo {
|
||||
return c.withDO(c.DO.Distinct(cols...))
|
||||
}
|
||||
|
||||
func (c collectionDo) Omit(cols ...field.Expr) ICollectionDo {
|
||||
return c.withDO(c.DO.Omit(cols...))
|
||||
}
|
||||
|
||||
func (c collectionDo) Join(table schema.Tabler, on ...field.Expr) ICollectionDo {
|
||||
return c.withDO(c.DO.Join(table, on...))
|
||||
}
|
||||
|
||||
func (c collectionDo) LeftJoin(table schema.Tabler, on ...field.Expr) ICollectionDo {
|
||||
return c.withDO(c.DO.LeftJoin(table, on...))
|
||||
}
|
||||
|
||||
func (c collectionDo) RightJoin(table schema.Tabler, on ...field.Expr) ICollectionDo {
|
||||
return c.withDO(c.DO.RightJoin(table, on...))
|
||||
}
|
||||
|
||||
func (c collectionDo) Group(cols ...field.Expr) ICollectionDo {
|
||||
return c.withDO(c.DO.Group(cols...))
|
||||
}
|
||||
|
||||
func (c collectionDo) Having(conds ...gen.Condition) ICollectionDo {
|
||||
return c.withDO(c.DO.Having(conds...))
|
||||
}
|
||||
|
||||
func (c collectionDo) Limit(limit int) ICollectionDo {
|
||||
return c.withDO(c.DO.Limit(limit))
|
||||
}
|
||||
|
||||
func (c collectionDo) Offset(offset int) ICollectionDo {
|
||||
return c.withDO(c.DO.Offset(offset))
|
||||
}
|
||||
|
||||
func (c collectionDo) Scopes(funcs ...func(gen.Dao) gen.Dao) ICollectionDo {
|
||||
return c.withDO(c.DO.Scopes(funcs...))
|
||||
}
|
||||
|
||||
func (c collectionDo) Unscoped() ICollectionDo {
|
||||
return c.withDO(c.DO.Unscoped())
|
||||
}
|
||||
|
||||
func (c collectionDo) Create(values ...*models.Collection) error {
|
||||
if len(values) == 0 {
|
||||
return nil
|
||||
}
|
||||
return c.DO.Create(values)
|
||||
}
|
||||
|
||||
func (c collectionDo) CreateInBatches(values []*models.Collection, batchSize int) error {
|
||||
return c.DO.CreateInBatches(values, batchSize)
|
||||
}
|
||||
|
||||
// Save : !!! underlying implementation is different with GORM
|
||||
// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
|
||||
func (c collectionDo) Save(values ...*models.Collection) error {
|
||||
if len(values) == 0 {
|
||||
return nil
|
||||
}
|
||||
return c.DO.Save(values)
|
||||
}
|
||||
|
||||
func (c collectionDo) First() (*models.Collection, error) {
|
||||
if result, err := c.DO.First(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*models.Collection), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c collectionDo) Take() (*models.Collection, error) {
|
||||
if result, err := c.DO.Take(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*models.Collection), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c collectionDo) Last() (*models.Collection, error) {
|
||||
if result, err := c.DO.Last(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*models.Collection), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c collectionDo) Find() ([]*models.Collection, error) {
|
||||
result, err := c.DO.Find()
|
||||
return result.([]*models.Collection), err
|
||||
}
|
||||
|
||||
func (c collectionDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*models.Collection, err error) {
|
||||
buf := make([]*models.Collection, 0, batchSize)
|
||||
err = c.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
|
||||
defer func() { results = append(results, buf...) }()
|
||||
return fc(tx, batch)
|
||||
})
|
||||
return results, err
|
||||
}
|
||||
|
||||
func (c collectionDo) FindInBatches(result *[]*models.Collection, batchSize int, fc func(tx gen.Dao, batch int) error) error {
|
||||
return c.DO.FindInBatches(result, batchSize, fc)
|
||||
}
|
||||
|
||||
func (c collectionDo) Attrs(attrs ...field.AssignExpr) ICollectionDo {
|
||||
return c.withDO(c.DO.Attrs(attrs...))
|
||||
}
|
||||
|
||||
func (c collectionDo) Assign(attrs ...field.AssignExpr) ICollectionDo {
|
||||
return c.withDO(c.DO.Assign(attrs...))
|
||||
}
|
||||
|
||||
func (c collectionDo) Joins(fields ...field.RelationField) ICollectionDo {
|
||||
for _, _f := range fields {
|
||||
c = *c.withDO(c.DO.Joins(_f))
|
||||
}
|
||||
return &c
|
||||
}
|
||||
|
||||
func (c collectionDo) Preload(fields ...field.RelationField) ICollectionDo {
|
||||
for _, _f := range fields {
|
||||
c = *c.withDO(c.DO.Preload(_f))
|
||||
}
|
||||
return &c
|
||||
}
|
||||
|
||||
func (c collectionDo) FirstOrInit() (*models.Collection, error) {
|
||||
if result, err := c.DO.FirstOrInit(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*models.Collection), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c collectionDo) FirstOrCreate() (*models.Collection, error) {
|
||||
if result, err := c.DO.FirstOrCreate(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*models.Collection), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c collectionDo) FindByPage(offset int, limit int) (result []*models.Collection, count int64, err error) {
|
||||
result, err = c.Offset(offset).Limit(limit).Find()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if size := len(result); 0 < limit && 0 < size && size < limit {
|
||||
count = int64(size + offset)
|
||||
return
|
||||
}
|
||||
|
||||
count, err = c.Offset(-1).Limit(-1).Count()
|
||||
return
|
||||
}
|
||||
|
||||
func (c collectionDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
|
||||
count, err = c.Count()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = c.Offset(offset).Limit(limit).Scan(result)
|
||||
return
|
||||
}
|
||||
|
||||
func (c collectionDo) Scan(result interface{}) (err error) {
|
||||
return c.DO.Scan(result)
|
||||
}
|
||||
|
||||
func (c collectionDo) Delete(models ...*models.Collection) (result gen.ResultInfo, err error) {
|
||||
return c.DO.Delete(models)
|
||||
}
|
||||
|
||||
func (c *collectionDo) withDO(do gen.Dao) *collectionDo {
|
||||
c.DO = *do.(*gen.DO)
|
||||
return c
|
||||
}
|
|
@ -16,39 +16,43 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
Q = new(Query)
|
||||
AccessToken *accessToken
|
||||
Emote *emote
|
||||
Feed *feed
|
||||
LoginProcessToken *loginProcessToken
|
||||
MediaMetadata *mediaMetadata
|
||||
Note *note
|
||||
NoteEdit *noteEdit
|
||||
NoteTag *noteTag
|
||||
NoteToAttachment *noteToAttachment
|
||||
NoteToBoost *noteToBoost
|
||||
NoteToEmote *noteToEmote
|
||||
NoteToFeed *noteToFeed
|
||||
NoteToPing *noteToPing
|
||||
Notification *notification
|
||||
Reaction *reaction
|
||||
RemoteServer *remoteServer
|
||||
RemoteServerMetadata *remoteServerMetadata
|
||||
Role *role
|
||||
User *user
|
||||
UserAuthMethod *userAuthMethod
|
||||
UserInfoField *userInfoField
|
||||
UserRemoteLinks *userRemoteLinks
|
||||
UserToBeing *userToBeing
|
||||
UserToPronoun *userToPronoun
|
||||
UserToRole *userToRole
|
||||
UserToTag *userToTag
|
||||
UserToUserRelation *userToUserRelation
|
||||
Q = new(Query)
|
||||
AccessToken *accessToken
|
||||
ActivitystreamsActivity *activitystreamsActivity
|
||||
Collection *collection
|
||||
Emote *emote
|
||||
Feed *feed
|
||||
LoginProcessToken *loginProcessToken
|
||||
MediaMetadata *mediaMetadata
|
||||
Note *note
|
||||
NoteEdit *noteEdit
|
||||
NoteTag *noteTag
|
||||
NoteToAttachment *noteToAttachment
|
||||
NoteToBoost *noteToBoost
|
||||
NoteToEmote *noteToEmote
|
||||
NoteToFeed *noteToFeed
|
||||
NoteToPing *noteToPing
|
||||
Notification *notification
|
||||
Reaction *reaction
|
||||
RemoteServer *remoteServer
|
||||
RemoteServerMetadata *remoteServerMetadata
|
||||
Role *role
|
||||
User *user
|
||||
UserAuthMethod *userAuthMethod
|
||||
UserInfoField *userInfoField
|
||||
UserRemoteLinks *userRemoteLinks
|
||||
UserToBeing *userToBeing
|
||||
UserToPronoun *userToPronoun
|
||||
UserToRole *userToRole
|
||||
UserToTag *userToTag
|
||||
UserToUserRelation *userToUserRelation
|
||||
)
|
||||
|
||||
func SetDefault(db *gorm.DB, opts ...gen.DOOption) {
|
||||
*Q = *Use(db, opts...)
|
||||
AccessToken = &Q.AccessToken
|
||||
ActivitystreamsActivity = &Q.ActivitystreamsActivity
|
||||
Collection = &Q.Collection
|
||||
Emote = &Q.Emote
|
||||
Feed = &Q.Feed
|
||||
LoginProcessToken = &Q.LoginProcessToken
|
||||
|
@ -79,101 +83,107 @@ func SetDefault(db *gorm.DB, opts ...gen.DOOption) {
|
|||
|
||||
func Use(db *gorm.DB, opts ...gen.DOOption) *Query {
|
||||
return &Query{
|
||||
db: db,
|
||||
AccessToken: newAccessToken(db, opts...),
|
||||
Emote: newEmote(db, opts...),
|
||||
Feed: newFeed(db, opts...),
|
||||
LoginProcessToken: newLoginProcessToken(db, opts...),
|
||||
MediaMetadata: newMediaMetadata(db, opts...),
|
||||
Note: newNote(db, opts...),
|
||||
NoteEdit: newNoteEdit(db, opts...),
|
||||
NoteTag: newNoteTag(db, opts...),
|
||||
NoteToAttachment: newNoteToAttachment(db, opts...),
|
||||
NoteToBoost: newNoteToBoost(db, opts...),
|
||||
NoteToEmote: newNoteToEmote(db, opts...),
|
||||
NoteToFeed: newNoteToFeed(db, opts...),
|
||||
NoteToPing: newNoteToPing(db, opts...),
|
||||
Notification: newNotification(db, opts...),
|
||||
Reaction: newReaction(db, opts...),
|
||||
RemoteServer: newRemoteServer(db, opts...),
|
||||
RemoteServerMetadata: newRemoteServerMetadata(db, opts...),
|
||||
Role: newRole(db, opts...),
|
||||
User: newUser(db, opts...),
|
||||
UserAuthMethod: newUserAuthMethod(db, opts...),
|
||||
UserInfoField: newUserInfoField(db, opts...),
|
||||
UserRemoteLinks: newUserRemoteLinks(db, opts...),
|
||||
UserToBeing: newUserToBeing(db, opts...),
|
||||
UserToPronoun: newUserToPronoun(db, opts...),
|
||||
UserToRole: newUserToRole(db, opts...),
|
||||
UserToTag: newUserToTag(db, opts...),
|
||||
UserToUserRelation: newUserToUserRelation(db, opts...),
|
||||
db: db,
|
||||
AccessToken: newAccessToken(db, opts...),
|
||||
ActivitystreamsActivity: newActivitystreamsActivity(db, opts...),
|
||||
Collection: newCollection(db, opts...),
|
||||
Emote: newEmote(db, opts...),
|
||||
Feed: newFeed(db, opts...),
|
||||
LoginProcessToken: newLoginProcessToken(db, opts...),
|
||||
MediaMetadata: newMediaMetadata(db, opts...),
|
||||
Note: newNote(db, opts...),
|
||||
NoteEdit: newNoteEdit(db, opts...),
|
||||
NoteTag: newNoteTag(db, opts...),
|
||||
NoteToAttachment: newNoteToAttachment(db, opts...),
|
||||
NoteToBoost: newNoteToBoost(db, opts...),
|
||||
NoteToEmote: newNoteToEmote(db, opts...),
|
||||
NoteToFeed: newNoteToFeed(db, opts...),
|
||||
NoteToPing: newNoteToPing(db, opts...),
|
||||
Notification: newNotification(db, opts...),
|
||||
Reaction: newReaction(db, opts...),
|
||||
RemoteServer: newRemoteServer(db, opts...),
|
||||
RemoteServerMetadata: newRemoteServerMetadata(db, opts...),
|
||||
Role: newRole(db, opts...),
|
||||
User: newUser(db, opts...),
|
||||
UserAuthMethod: newUserAuthMethod(db, opts...),
|
||||
UserInfoField: newUserInfoField(db, opts...),
|
||||
UserRemoteLinks: newUserRemoteLinks(db, opts...),
|
||||
UserToBeing: newUserToBeing(db, opts...),
|
||||
UserToPronoun: newUserToPronoun(db, opts...),
|
||||
UserToRole: newUserToRole(db, opts...),
|
||||
UserToTag: newUserToTag(db, opts...),
|
||||
UserToUserRelation: newUserToUserRelation(db, opts...),
|
||||
}
|
||||
}
|
||||
|
||||
type Query struct {
|
||||
db *gorm.DB
|
||||
|
||||
AccessToken accessToken
|
||||
Emote emote
|
||||
Feed feed
|
||||
LoginProcessToken loginProcessToken
|
||||
MediaMetadata mediaMetadata
|
||||
Note note
|
||||
NoteEdit noteEdit
|
||||
NoteTag noteTag
|
||||
NoteToAttachment noteToAttachment
|
||||
NoteToBoost noteToBoost
|
||||
NoteToEmote noteToEmote
|
||||
NoteToFeed noteToFeed
|
||||
NoteToPing noteToPing
|
||||
Notification notification
|
||||
Reaction reaction
|
||||
RemoteServer remoteServer
|
||||
RemoteServerMetadata remoteServerMetadata
|
||||
Role role
|
||||
User user
|
||||
UserAuthMethod userAuthMethod
|
||||
UserInfoField userInfoField
|
||||
UserRemoteLinks userRemoteLinks
|
||||
UserToBeing userToBeing
|
||||
UserToPronoun userToPronoun
|
||||
UserToRole userToRole
|
||||
UserToTag userToTag
|
||||
UserToUserRelation userToUserRelation
|
||||
AccessToken accessToken
|
||||
ActivitystreamsActivity activitystreamsActivity
|
||||
Collection collection
|
||||
Emote emote
|
||||
Feed feed
|
||||
LoginProcessToken loginProcessToken
|
||||
MediaMetadata mediaMetadata
|
||||
Note note
|
||||
NoteEdit noteEdit
|
||||
NoteTag noteTag
|
||||
NoteToAttachment noteToAttachment
|
||||
NoteToBoost noteToBoost
|
||||
NoteToEmote noteToEmote
|
||||
NoteToFeed noteToFeed
|
||||
NoteToPing noteToPing
|
||||
Notification notification
|
||||
Reaction reaction
|
||||
RemoteServer remoteServer
|
||||
RemoteServerMetadata remoteServerMetadata
|
||||
Role role
|
||||
User user
|
||||
UserAuthMethod userAuthMethod
|
||||
UserInfoField userInfoField
|
||||
UserRemoteLinks userRemoteLinks
|
||||
UserToBeing userToBeing
|
||||
UserToPronoun userToPronoun
|
||||
UserToRole userToRole
|
||||
UserToTag userToTag
|
||||
UserToUserRelation userToUserRelation
|
||||
}
|
||||
|
||||
func (q *Query) Available() bool { return q.db != nil }
|
||||
|
||||
func (q *Query) clone(db *gorm.DB) *Query {
|
||||
return &Query{
|
||||
db: db,
|
||||
AccessToken: q.AccessToken.clone(db),
|
||||
Emote: q.Emote.clone(db),
|
||||
Feed: q.Feed.clone(db),
|
||||
LoginProcessToken: q.LoginProcessToken.clone(db),
|
||||
MediaMetadata: q.MediaMetadata.clone(db),
|
||||
Note: q.Note.clone(db),
|
||||
NoteEdit: q.NoteEdit.clone(db),
|
||||
NoteTag: q.NoteTag.clone(db),
|
||||
NoteToAttachment: q.NoteToAttachment.clone(db),
|
||||
NoteToBoost: q.NoteToBoost.clone(db),
|
||||
NoteToEmote: q.NoteToEmote.clone(db),
|
||||
NoteToFeed: q.NoteToFeed.clone(db),
|
||||
NoteToPing: q.NoteToPing.clone(db),
|
||||
Notification: q.Notification.clone(db),
|
||||
Reaction: q.Reaction.clone(db),
|
||||
RemoteServer: q.RemoteServer.clone(db),
|
||||
RemoteServerMetadata: q.RemoteServerMetadata.clone(db),
|
||||
Role: q.Role.clone(db),
|
||||
User: q.User.clone(db),
|
||||
UserAuthMethod: q.UserAuthMethod.clone(db),
|
||||
UserInfoField: q.UserInfoField.clone(db),
|
||||
UserRemoteLinks: q.UserRemoteLinks.clone(db),
|
||||
UserToBeing: q.UserToBeing.clone(db),
|
||||
UserToPronoun: q.UserToPronoun.clone(db),
|
||||
UserToRole: q.UserToRole.clone(db),
|
||||
UserToTag: q.UserToTag.clone(db),
|
||||
UserToUserRelation: q.UserToUserRelation.clone(db),
|
||||
db: db,
|
||||
AccessToken: q.AccessToken.clone(db),
|
||||
ActivitystreamsActivity: q.ActivitystreamsActivity.clone(db),
|
||||
Collection: q.Collection.clone(db),
|
||||
Emote: q.Emote.clone(db),
|
||||
Feed: q.Feed.clone(db),
|
||||
LoginProcessToken: q.LoginProcessToken.clone(db),
|
||||
MediaMetadata: q.MediaMetadata.clone(db),
|
||||
Note: q.Note.clone(db),
|
||||
NoteEdit: q.NoteEdit.clone(db),
|
||||
NoteTag: q.NoteTag.clone(db),
|
||||
NoteToAttachment: q.NoteToAttachment.clone(db),
|
||||
NoteToBoost: q.NoteToBoost.clone(db),
|
||||
NoteToEmote: q.NoteToEmote.clone(db),
|
||||
NoteToFeed: q.NoteToFeed.clone(db),
|
||||
NoteToPing: q.NoteToPing.clone(db),
|
||||
Notification: q.Notification.clone(db),
|
||||
Reaction: q.Reaction.clone(db),
|
||||
RemoteServer: q.RemoteServer.clone(db),
|
||||
RemoteServerMetadata: q.RemoteServerMetadata.clone(db),
|
||||
Role: q.Role.clone(db),
|
||||
User: q.User.clone(db),
|
||||
UserAuthMethod: q.UserAuthMethod.clone(db),
|
||||
UserInfoField: q.UserInfoField.clone(db),
|
||||
UserRemoteLinks: q.UserRemoteLinks.clone(db),
|
||||
UserToBeing: q.UserToBeing.clone(db),
|
||||
UserToPronoun: q.UserToPronoun.clone(db),
|
||||
UserToRole: q.UserToRole.clone(db),
|
||||
UserToTag: q.UserToTag.clone(db),
|
||||
UserToUserRelation: q.UserToUserRelation.clone(db),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,96 +197,102 @@ func (q *Query) WriteDB() *Query {
|
|||
|
||||
func (q *Query) ReplaceDB(db *gorm.DB) *Query {
|
||||
return &Query{
|
||||
db: db,
|
||||
AccessToken: q.AccessToken.replaceDB(db),
|
||||
Emote: q.Emote.replaceDB(db),
|
||||
Feed: q.Feed.replaceDB(db),
|
||||
LoginProcessToken: q.LoginProcessToken.replaceDB(db),
|
||||
MediaMetadata: q.MediaMetadata.replaceDB(db),
|
||||
Note: q.Note.replaceDB(db),
|
||||
NoteEdit: q.NoteEdit.replaceDB(db),
|
||||
NoteTag: q.NoteTag.replaceDB(db),
|
||||
NoteToAttachment: q.NoteToAttachment.replaceDB(db),
|
||||
NoteToBoost: q.NoteToBoost.replaceDB(db),
|
||||
NoteToEmote: q.NoteToEmote.replaceDB(db),
|
||||
NoteToFeed: q.NoteToFeed.replaceDB(db),
|
||||
NoteToPing: q.NoteToPing.replaceDB(db),
|
||||
Notification: q.Notification.replaceDB(db),
|
||||
Reaction: q.Reaction.replaceDB(db),
|
||||
RemoteServer: q.RemoteServer.replaceDB(db),
|
||||
RemoteServerMetadata: q.RemoteServerMetadata.replaceDB(db),
|
||||
Role: q.Role.replaceDB(db),
|
||||
User: q.User.replaceDB(db),
|
||||
UserAuthMethod: q.UserAuthMethod.replaceDB(db),
|
||||
UserInfoField: q.UserInfoField.replaceDB(db),
|
||||
UserRemoteLinks: q.UserRemoteLinks.replaceDB(db),
|
||||
UserToBeing: q.UserToBeing.replaceDB(db),
|
||||
UserToPronoun: q.UserToPronoun.replaceDB(db),
|
||||
UserToRole: q.UserToRole.replaceDB(db),
|
||||
UserToTag: q.UserToTag.replaceDB(db),
|
||||
UserToUserRelation: q.UserToUserRelation.replaceDB(db),
|
||||
db: db,
|
||||
AccessToken: q.AccessToken.replaceDB(db),
|
||||
ActivitystreamsActivity: q.ActivitystreamsActivity.replaceDB(db),
|
||||
Collection: q.Collection.replaceDB(db),
|
||||
Emote: q.Emote.replaceDB(db),
|
||||
Feed: q.Feed.replaceDB(db),
|
||||
LoginProcessToken: q.LoginProcessToken.replaceDB(db),
|
||||
MediaMetadata: q.MediaMetadata.replaceDB(db),
|
||||
Note: q.Note.replaceDB(db),
|
||||
NoteEdit: q.NoteEdit.replaceDB(db),
|
||||
NoteTag: q.NoteTag.replaceDB(db),
|
||||
NoteToAttachment: q.NoteToAttachment.replaceDB(db),
|
||||
NoteToBoost: q.NoteToBoost.replaceDB(db),
|
||||
NoteToEmote: q.NoteToEmote.replaceDB(db),
|
||||
NoteToFeed: q.NoteToFeed.replaceDB(db),
|
||||
NoteToPing: q.NoteToPing.replaceDB(db),
|
||||
Notification: q.Notification.replaceDB(db),
|
||||
Reaction: q.Reaction.replaceDB(db),
|
||||
RemoteServer: q.RemoteServer.replaceDB(db),
|
||||
RemoteServerMetadata: q.RemoteServerMetadata.replaceDB(db),
|
||||
Role: q.Role.replaceDB(db),
|
||||
User: q.User.replaceDB(db),
|
||||
UserAuthMethod: q.UserAuthMethod.replaceDB(db),
|
||||
UserInfoField: q.UserInfoField.replaceDB(db),
|
||||
UserRemoteLinks: q.UserRemoteLinks.replaceDB(db),
|
||||
UserToBeing: q.UserToBeing.replaceDB(db),
|
||||
UserToPronoun: q.UserToPronoun.replaceDB(db),
|
||||
UserToRole: q.UserToRole.replaceDB(db),
|
||||
UserToTag: q.UserToTag.replaceDB(db),
|
||||
UserToUserRelation: q.UserToUserRelation.replaceDB(db),
|
||||
}
|
||||
}
|
||||
|
||||
type queryCtx struct {
|
||||
AccessToken IAccessTokenDo
|
||||
Emote IEmoteDo
|
||||
Feed IFeedDo
|
||||
LoginProcessToken ILoginProcessTokenDo
|
||||
MediaMetadata IMediaMetadataDo
|
||||
Note INoteDo
|
||||
NoteEdit INoteEditDo
|
||||
NoteTag INoteTagDo
|
||||
NoteToAttachment INoteToAttachmentDo
|
||||
NoteToBoost INoteToBoostDo
|
||||
NoteToEmote INoteToEmoteDo
|
||||
NoteToFeed INoteToFeedDo
|
||||
NoteToPing INoteToPingDo
|
||||
Notification INotificationDo
|
||||
Reaction IReactionDo
|
||||
RemoteServer IRemoteServerDo
|
||||
RemoteServerMetadata IRemoteServerMetadataDo
|
||||
Role IRoleDo
|
||||
User IUserDo
|
||||
UserAuthMethod IUserAuthMethodDo
|
||||
UserInfoField IUserInfoFieldDo
|
||||
UserRemoteLinks IUserRemoteLinksDo
|
||||
UserToBeing IUserToBeingDo
|
||||
UserToPronoun IUserToPronounDo
|
||||
UserToRole IUserToRoleDo
|
||||
UserToTag IUserToTagDo
|
||||
UserToUserRelation IUserToUserRelationDo
|
||||
AccessToken IAccessTokenDo
|
||||
ActivitystreamsActivity IActivitystreamsActivityDo
|
||||
Collection ICollectionDo
|
||||
Emote IEmoteDo
|
||||
Feed IFeedDo
|
||||
LoginProcessToken ILoginProcessTokenDo
|
||||
MediaMetadata IMediaMetadataDo
|
||||
Note INoteDo
|
||||
NoteEdit INoteEditDo
|
||||
NoteTag INoteTagDo
|
||||
NoteToAttachment INoteToAttachmentDo
|
||||
NoteToBoost INoteToBoostDo
|
||||
NoteToEmote INoteToEmoteDo
|
||||
NoteToFeed INoteToFeedDo
|
||||
NoteToPing INoteToPingDo
|
||||
Notification INotificationDo
|
||||
Reaction IReactionDo
|
||||
RemoteServer IRemoteServerDo
|
||||
RemoteServerMetadata IRemoteServerMetadataDo
|
||||
Role IRoleDo
|
||||
User IUserDo
|
||||
UserAuthMethod IUserAuthMethodDo
|
||||
UserInfoField IUserInfoFieldDo
|
||||
UserRemoteLinks IUserRemoteLinksDo
|
||||
UserToBeing IUserToBeingDo
|
||||
UserToPronoun IUserToPronounDo
|
||||
UserToRole IUserToRoleDo
|
||||
UserToTag IUserToTagDo
|
||||
UserToUserRelation IUserToUserRelationDo
|
||||
}
|
||||
|
||||
func (q *Query) WithContext(ctx context.Context) *queryCtx {
|
||||
return &queryCtx{
|
||||
AccessToken: q.AccessToken.WithContext(ctx),
|
||||
Emote: q.Emote.WithContext(ctx),
|
||||
Feed: q.Feed.WithContext(ctx),
|
||||
LoginProcessToken: q.LoginProcessToken.WithContext(ctx),
|
||||
MediaMetadata: q.MediaMetadata.WithContext(ctx),
|
||||
Note: q.Note.WithContext(ctx),
|
||||
NoteEdit: q.NoteEdit.WithContext(ctx),
|
||||
NoteTag: q.NoteTag.WithContext(ctx),
|
||||
NoteToAttachment: q.NoteToAttachment.WithContext(ctx),
|
||||
NoteToBoost: q.NoteToBoost.WithContext(ctx),
|
||||
NoteToEmote: q.NoteToEmote.WithContext(ctx),
|
||||
NoteToFeed: q.NoteToFeed.WithContext(ctx),
|
||||
NoteToPing: q.NoteToPing.WithContext(ctx),
|
||||
Notification: q.Notification.WithContext(ctx),
|
||||
Reaction: q.Reaction.WithContext(ctx),
|
||||
RemoteServer: q.RemoteServer.WithContext(ctx),
|
||||
RemoteServerMetadata: q.RemoteServerMetadata.WithContext(ctx),
|
||||
Role: q.Role.WithContext(ctx),
|
||||
User: q.User.WithContext(ctx),
|
||||
UserAuthMethod: q.UserAuthMethod.WithContext(ctx),
|
||||
UserInfoField: q.UserInfoField.WithContext(ctx),
|
||||
UserRemoteLinks: q.UserRemoteLinks.WithContext(ctx),
|
||||
UserToBeing: q.UserToBeing.WithContext(ctx),
|
||||
UserToPronoun: q.UserToPronoun.WithContext(ctx),
|
||||
UserToRole: q.UserToRole.WithContext(ctx),
|
||||
UserToTag: q.UserToTag.WithContext(ctx),
|
||||
UserToUserRelation: q.UserToUserRelation.WithContext(ctx),
|
||||
AccessToken: q.AccessToken.WithContext(ctx),
|
||||
ActivitystreamsActivity: q.ActivitystreamsActivity.WithContext(ctx),
|
||||
Collection: q.Collection.WithContext(ctx),
|
||||
Emote: q.Emote.WithContext(ctx),
|
||||
Feed: q.Feed.WithContext(ctx),
|
||||
LoginProcessToken: q.LoginProcessToken.WithContext(ctx),
|
||||
MediaMetadata: q.MediaMetadata.WithContext(ctx),
|
||||
Note: q.Note.WithContext(ctx),
|
||||
NoteEdit: q.NoteEdit.WithContext(ctx),
|
||||
NoteTag: q.NoteTag.WithContext(ctx),
|
||||
NoteToAttachment: q.NoteToAttachment.WithContext(ctx),
|
||||
NoteToBoost: q.NoteToBoost.WithContext(ctx),
|
||||
NoteToEmote: q.NoteToEmote.WithContext(ctx),
|
||||
NoteToFeed: q.NoteToFeed.WithContext(ctx),
|
||||
NoteToPing: q.NoteToPing.WithContext(ctx),
|
||||
Notification: q.Notification.WithContext(ctx),
|
||||
Reaction: q.Reaction.WithContext(ctx),
|
||||
RemoteServer: q.RemoteServer.WithContext(ctx),
|
||||
RemoteServerMetadata: q.RemoteServerMetadata.WithContext(ctx),
|
||||
Role: q.Role.WithContext(ctx),
|
||||
User: q.User.WithContext(ctx),
|
||||
UserAuthMethod: q.UserAuthMethod.WithContext(ctx),
|
||||
UserInfoField: q.UserInfoField.WithContext(ctx),
|
||||
UserRemoteLinks: q.UserRemoteLinks.WithContext(ctx),
|
||||
UserToBeing: q.UserToBeing.WithContext(ctx),
|
||||
UserToPronoun: q.UserToPronoun.WithContext(ctx),
|
||||
UserToRole: q.UserToRole.WithContext(ctx),
|
||||
UserToTag: q.UserToTag.WithContext(ctx),
|
||||
UserToUserRelation: q.UserToUserRelation.WithContext(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package models
|
|||
|
||||
// A list of all models stored in the database
|
||||
var AllTypes = []any{
|
||||
&Collection{},
|
||||
&ActivitystreamsActivity{},
|
||||
&Emote{},
|
||||
&Feed{},
|
||||
|
|
7
storage-new/models/ActivityCollection.go
Normal file
7
storage-new/models/ActivityCollection.go
Normal file
|
@ -0,0 +1,7 @@
|
|||
package models
|
||||
|
||||
type Collection struct {
|
||||
Id string `gorm:"primarykey"`
|
||||
TargetId string
|
||||
TargetType uint32
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package models
|
||||
|
||||
type ActivitystreamsActivity struct {
|
||||
Id string `gorm:"primarykey"`
|
||||
Type string `gorm:"type:activitystreams_activity_type"`
|
||||
ObjectId string
|
||||
ObjectType uint32 // Target type: ActivitystreamsActivityTargetType
|
||||
|
|
|
@ -68,6 +68,7 @@ func AttemptReconnect() {
|
|||
// HandleReconnectError checks if the given error requires
|
||||
// a reconnect attempt. If it does, it also starts
|
||||
// a reconnection attempt.
|
||||
// Returns true if a reconnect has been started
|
||||
func HandleReconnectError(errToCheck error) bool {
|
||||
if _, ok := errToCheck.(*pgconn.ConnectError); ok {
|
||||
go AttemptReconnect()
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[general]
|
||||
protocol = "https"
|
||||
domain = "serveo.net"
|
||||
subdomain = "e8f7573481d6b2311fb076f4190ac852"
|
||||
domain = "lhr.life"
|
||||
subdomain = "61f6e346a99d58"
|
||||
private_port = 8080
|
||||
public_port = 443
|
||||
|
||||
|
|
|
@ -14,6 +14,8 @@ import (
|
|||
"net/http"
|
||||
|
||||
webutils "git.mstar.dev/mstar/goutils/http"
|
||||
|
||||
webmiddleware "git.mstar.dev/mstar/linstrom/web/public/middleware"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
|
@ -36,7 +38,13 @@ func New(addr string) *Server {
|
|||
Addr: addr,
|
||||
Handler: webutils.ChainMiddlewares(
|
||||
handler,
|
||||
webutils.BuildLoggingMiddleware(map[string]string{"server": "debug"}),
|
||||
webutils.BuildLoggingMiddleware(
|
||||
true,
|
||||
[]string{"/assets"},
|
||||
map[string]string{"server": "debug"},
|
||||
),
|
||||
webmiddleware.AppendFullPathMiddleware,
|
||||
webmiddleware.TraceRequestInfoMiddleware,
|
||||
),
|
||||
}
|
||||
return &Server{&web}
|
||||
|
|
|
@ -9,8 +9,14 @@ func BuildActivitypubRouter() http.Handler {
|
|||
router := http.NewServeMux()
|
||||
router.HandleFunc("/user/{id}", users)
|
||||
router.HandleFunc("/user/{id}/inbox", userInbox)
|
||||
router.HandleFunc("/activity/accept/{id}", activityAccept)
|
||||
router.HandleFunc("/activity/create/{id}", activityCreate)
|
||||
router.HandleFunc("/activity/delete/{id}", activityDelete)
|
||||
router.HandleFunc("/activity/reject/{id}", activityReject)
|
||||
router.HandleFunc("/activity/update/{id}", activityUpdate)
|
||||
router.HandleFunc("/note/{id}", objectNote)
|
||||
router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprint(w, "in ap")
|
||||
_, _ = fmt.Fprint(w, "in ap")
|
||||
})
|
||||
return router
|
||||
}
|
||||
|
|
|
@ -54,7 +54,6 @@ func users(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
log := hlog.FromRequest(r)
|
||||
userId := r.PathValue("id")
|
||||
log.Debug().Any("headers", r.Header).Msg("request headers")
|
||||
user, err := dbgen.User.Where(dbgen.User.ID.Eq(userId)).
|
||||
Preload(dbgen.User.Icon).Preload(dbgen.User.Banner).
|
||||
Preload(dbgen.User.BeingTypes).
|
||||
|
|
|
@ -1 +1,5 @@
|
|||
package activitypub
|
||||
|
||||
import "net/http"
|
||||
|
||||
func activityAccept(w http.ResponseWriter, r *http.Request) {}
|
||||
|
|
|
@ -1 +1,23 @@
|
|||
package activitypub
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Announce is boost
|
||||
|
||||
type activityAnnounceOut struct {
|
||||
Context any `json:"@context,omitempty"`
|
||||
Id string
|
||||
Type string // Always "Announce"
|
||||
Actor string // The one doing the boost
|
||||
Published time.Time
|
||||
To []string
|
||||
CC []string
|
||||
Object string // Link to object being boosted
|
||||
}
|
||||
|
||||
func announceFromStorage(ctx context.Context, id string) (*activityAnnounceOut, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
|
|
@ -1 +1,94 @@
|
|||
package activitypub
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
webutils "git.mstar.dev/mstar/goutils/http"
|
||||
"github.com/rs/zerolog/hlog"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"git.mstar.dev/mstar/linstrom/activitypub"
|
||||
"git.mstar.dev/mstar/linstrom/config"
|
||||
"git.mstar.dev/mstar/linstrom/storage-new"
|
||||
"git.mstar.dev/mstar/linstrom/storage-new/dbgen"
|
||||
"git.mstar.dev/mstar/linstrom/storage-new/models"
|
||||
)
|
||||
|
||||
type activityCreateOut struct {
|
||||
Context any `json:"@context,omitempty"`
|
||||
Id string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Actor string `json:"actor"`
|
||||
Object any `json:"object"`
|
||||
}
|
||||
|
||||
func activityCreate(w http.ResponseWriter, r *http.Request) {
|
||||
log := hlog.FromRequest(r)
|
||||
id := r.PathValue("id")
|
||||
activity, err := createFromStorage(r.Context(), id)
|
||||
switch err {
|
||||
case gorm.ErrRecordNotFound:
|
||||
webutils.ProblemDetailsStatusOnly(w, http.StatusNotFound)
|
||||
case nil:
|
||||
activity.Context = activitypub.BaseLdContext
|
||||
data, err := json.Marshal(activity)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Any("activity", activity).Msg("Failed to marshal create activity")
|
||||
webutils.ProblemDetailsStatusOnly(w, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Header().Add("Content-Type", "application/activity+json")
|
||||
fmt.Fprint(w, string(data))
|
||||
default:
|
||||
if storage.HandleReconnectError(err) {
|
||||
log.Error().Err(err).Msg("Connection failed, restart attempt started")
|
||||
} else {
|
||||
log.Error().Err(err).Msg("Failed to get create activity from db")
|
||||
}
|
||||
webutils.ProblemDetailsStatusOnly(w, http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
// Find a create activity from the db and format it for activitypub reads
|
||||
// Does not set the context for the activity, in case the activity is embedded
|
||||
// in another activity or object. That's the responsibility of the handler
|
||||
// getting the final result
|
||||
func createFromStorage(ctx context.Context, id string) (*activityCreateOut, error) {
|
||||
// log := log.Ctx(ctx)
|
||||
asa := dbgen.ActivitystreamsActivity
|
||||
activity, err := asa.Where(asa.Type.Eq(string(models.ActivityCreate))).
|
||||
Where(asa.Id.Eq(id)).
|
||||
First()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch models.ActivitystreamsActivityTargetType(activity.ObjectType) {
|
||||
case models.ActivitystreamsActivityTargetNote:
|
||||
note, err := noteFromStorage(ctx, activity.ObjectId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out := activityCreateOut{
|
||||
Id: config.GlobalConfig.General.GetFullPublicUrl() + "/api/activitypub/create/" + id,
|
||||
Type: "Create",
|
||||
Actor: note.AttributedTo,
|
||||
Object: note,
|
||||
}
|
||||
return &out, nil
|
||||
case models.ActivitystreamsActivityTargetBoost:
|
||||
panic("Not implemented")
|
||||
case models.ActivitystreamsActivityTargetReaction:
|
||||
panic("Not implemented")
|
||||
case models.ActivitystreamsActivityTargetActivity:
|
||||
panic("Not implemented")
|
||||
case models.ActivitystreamsActivityTargetUser:
|
||||
panic("Not implemented")
|
||||
case models.ActivitystreamsActivityTargetUnknown:
|
||||
panic("Not implemented")
|
||||
default:
|
||||
panic("Not implemented")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1,5 @@
|
|||
package activitypub
|
||||
|
||||
import "net/http"
|
||||
|
||||
func activityDelete(w http.ResponseWriter, r *http.Request) {}
|
||||
|
|
|
@ -1 +1,5 @@
|
|||
package activitypub
|
||||
|
||||
import "net/http"
|
||||
|
||||
func activityReject(w http.ResponseWriter, r *http.Request) {}
|
||||
|
|
|
@ -1 +1,5 @@
|
|||
package activitypub
|
||||
|
||||
import "net/http"
|
||||
|
||||
func activityUpdate(w http.ResponseWriter, r *http.Request) {}
|
||||
|
|
30
web/public/api/activitypub/collection.go
Normal file
30
web/public/api/activitypub/collection.go
Normal file
|
@ -0,0 +1,30 @@
|
|||
package activitypub
|
||||
|
||||
import "net/http"
|
||||
|
||||
// Used for both unordered and ordered
|
||||
type collectionOut struct {
|
||||
Context any
|
||||
Summary string
|
||||
Type string
|
||||
Items []any
|
||||
Id string
|
||||
TotalItems int
|
||||
First *collectionPageOut
|
||||
}
|
||||
|
||||
// Used for both unordered and ordered
|
||||
type collectionPageOut struct {
|
||||
Context any
|
||||
Type string
|
||||
Id string
|
||||
PartOf string
|
||||
Next string
|
||||
Items []any
|
||||
}
|
||||
|
||||
// Unordered collections handler
|
||||
func collections(w http.ResponseWriter, r *http.Request) {}
|
||||
|
||||
// Ordered collections handler
|
||||
func orderedCollections(w http.ResponseWriter, r *http.Request) {}
|
|
@ -1 +1,102 @@
|
|||
package activitypub
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
webutils "git.mstar.dev/mstar/goutils/http"
|
||||
"github.com/rs/zerolog/hlog"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"git.mstar.dev/mstar/linstrom/activitypub"
|
||||
"git.mstar.dev/mstar/linstrom/config"
|
||||
"git.mstar.dev/mstar/linstrom/storage-new"
|
||||
"git.mstar.dev/mstar/linstrom/storage-new/dbgen"
|
||||
)
|
||||
|
||||
type objectNoteOut struct {
|
||||
// Context should be set, if needed, by the endpoint handler
|
||||
Context any `json:"@context,omitempty"`
|
||||
|
||||
// Attributes below set from storage
|
||||
|
||||
Id string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Summary *string `json:"summary"`
|
||||
InReplyTo *string `json:"inReplyTo"`
|
||||
Published time.Time `json:"published"`
|
||||
Url string `json:"url"`
|
||||
AttributedTo string `json:"attributedTo"`
|
||||
To []string `json:"to"`
|
||||
// CC []string `json:"cc"` // FIXME: Uncomment once followers collection implemented
|
||||
Sensitive bool `json:"sensitive"`
|
||||
AtomUri string `json:"atomUri"`
|
||||
InReplyToAtomUri *string `json:"inReplyToAtomUri"`
|
||||
// Conversation string `json:"conversation"` // FIXME: Uncomment once understood what this field wants
|
||||
Content string `json:"content"`
|
||||
// ContentMap map[string]string `json:"content_map"` // TODO: Uncomment once/if support for multiple languages available
|
||||
// Attachments []string `json:"attachments"` // FIXME: Change this to document type
|
||||
// Tags []string `json:"tags"` // FIXME: Change this to hashtag type
|
||||
// Replies any `json:"replies"` // FIXME: Change this to collection type embedding first page
|
||||
// Likes any `json:"likes"` // FIXME: Change this to collection
|
||||
// Shares any `json:"shares"` // FIXME: Change this to collection, is boosts
|
||||
}
|
||||
|
||||
func objectNote(w http.ResponseWriter, r *http.Request) {
|
||||
id := r.PathValue("id")
|
||||
log := hlog.FromRequest(r)
|
||||
note, err := noteFromStorage(r.Context(), id)
|
||||
switch err {
|
||||
case gorm.ErrRecordNotFound:
|
||||
webutils.ProblemDetailsStatusOnly(w, http.StatusNotFound)
|
||||
return
|
||||
case nil:
|
||||
note.Context = activitypub.BaseLdContext
|
||||
data, err := json.Marshal(note)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Any("activity", note).Msg("Failed to marshal create activity")
|
||||
webutils.ProblemDetailsStatusOnly(w, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Header().Add("Content-Type", "application/activity+json")
|
||||
fmt.Fprint(w, string(data))
|
||||
default:
|
||||
if storage.HandleReconnectError(err) {
|
||||
log.Error().Err(err).Msg("Connection failed, restart attempt started")
|
||||
} else {
|
||||
log.Error().Err(err).Msg("Failed to get create activity from db")
|
||||
}
|
||||
webutils.ProblemDetailsStatusOnly(w, http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
func noteFromStorage(ctx context.Context, id string) (*objectNoteOut, error) {
|
||||
note, err := dbgen.Note.Where(dbgen.Note.ID.Eq(id)).Preload(dbgen.Note.Creator).First()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data := &objectNoteOut{
|
||||
Id: config.GlobalConfig.General.GetFullPublicUrl() + "/api/activitypub/note/" + id,
|
||||
Type: "Note",
|
||||
Published: note.CreatedAt,
|
||||
AttributedTo: config.GlobalConfig.General.GetFullPublicUrl() + "/api/activitypub/user/" + note.CreatorId,
|
||||
Content: note.RawContent, // FIXME: Escape content
|
||||
Url: config.GlobalConfig.General.GetFullPublicUrl() + "/@" + note.Creator.Username + "/" + id,
|
||||
To: []string{
|
||||
"https://www.w3.org/ns/activitystreams#Public",
|
||||
}, // FIXME: Replace with proper targets, not always public
|
||||
AtomUri: config.GlobalConfig.General.GetFullPublicUrl() + "/api/activitypub/object/" + id,
|
||||
}
|
||||
if note.RepliesTo.Valid {
|
||||
data.InReplyTo = ¬e.RepliesTo.String
|
||||
data.InReplyToAtomUri = ¬e.RepliesTo.String
|
||||
}
|
||||
if note.ContentWarning.Valid {
|
||||
data.Summary = ¬e.ContentWarning.String
|
||||
data.Sensitive = true
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
|
|
@ -64,13 +64,13 @@ func BuildAuthorizedFetchCheck(forNonGet bool, forGet bool) webutils.HandlerBuil
|
|||
|
||||
if !config.GlobalConfig.Experimental.AuthFetchForServerActor &&
|
||||
strings.Contains(path, storage.ServerActorId) {
|
||||
log.Info().Msg("Server actor requested, no auth")
|
||||
log.Debug().Msg("Server actor requested, no auth")
|
||||
h.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
// Not an always open path, check methods
|
||||
if r.Method == "GET" && !forGet {
|
||||
log.Info().Msg("Get request to AP resources don't need signature")
|
||||
log.Debug().Msg("Get request to AP resources don't need signature")
|
||||
h.ServeHTTP(w, r)
|
||||
return
|
||||
} else if !forGet && !forNonGet {
|
||||
|
@ -78,7 +78,7 @@ func BuildAuthorizedFetchCheck(forNonGet bool, forGet bool) webutils.HandlerBuil
|
|||
h.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
log.Info().Msg("Need signature for AP request")
|
||||
log.Debug().Msg("Need signature for AP request")
|
||||
rawDate := r.Header.Get("Date")
|
||||
date, err := http.ParseTime(rawDate)
|
||||
if err != nil {
|
||||
|
|
28
web/public/middleware/traceRequestInfo.go
Normal file
28
web/public/middleware/traceRequestInfo.go
Normal file
|
@ -0,0 +1,28 @@
|
|||
package webmiddleware
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
webutils "git.mstar.dev/mstar/goutils/http"
|
||||
"github.com/rs/zerolog/hlog"
|
||||
)
|
||||
|
||||
func TraceRequestInfoMiddleware(h http.Handler) http.Handler {
|
||||
return webutils.ChainMiddlewares(
|
||||
h,
|
||||
hlog.AccessHandler(func(r *http.Request, status, size int, duration time.Duration) {
|
||||
body, _ := io.ReadAll(r.Body)
|
||||
r.Body = io.NopCloser(bytes.NewReader(body))
|
||||
hlog.FromRequest(r).Trace().Any("headers", r.Header).
|
||||
Bytes("body", body).
|
||||
Str("method", r.Method).
|
||||
Stringer("url", r.URL).
|
||||
Int("status", status).
|
||||
Int("size", size).
|
||||
Dur("duration", duration)
|
||||
}),
|
||||
)
|
||||
}
|
|
@ -59,8 +59,13 @@ func New(addr string, duckImg *string, duckFs fs.FS) *Server {
|
|||
server := http.Server{
|
||||
Handler: webutils.ChainMiddlewares(
|
||||
handler,
|
||||
webutils.BuildLoggingMiddleware(map[string]string{"server": "public"}),
|
||||
webutils.BuildLoggingMiddleware(
|
||||
true,
|
||||
[]string{"/assets"},
|
||||
map[string]string{"server": "public"},
|
||||
),
|
||||
webmiddleware.AppendFullPathMiddleware,
|
||||
webmiddleware.TraceRequestInfoMiddleware,
|
||||
),
|
||||
Addr: addr,
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue