diff options
-rw-r--r-- | CacheDatabase.go | 431 | ||||
-rw-r--r-- | Database.go | 75 | ||||
-rw-r--r-- | Follow.go | 168 | ||||
-rw-r--r-- | OutboxPost.go | 124 | ||||
-rw-r--r-- | databaseschema.psql | 72 | ||||
-rw-r--r-- | main.go | 56 | ||||
-rw-r--r-- | outboxGet.go | 9 |
7 files changed, 737 insertions, 198 deletions
diff --git a/CacheDatabase.go b/CacheDatabase.go new file mode 100644 index 0000000..ebb84df --- /dev/null +++ b/CacheDatabase.go @@ -0,0 +1,431 @@ +package main + +import "fmt" +import "database/sql" +import _ "github.com/lib/pq" + +func WriteObjectToCache(db *sql.DB, obj ObjectBase) ObjectBase { + if len(obj.Attachment) > 0 { + if obj.Preview.Href != "" { + WritePreviewToCache(db, *obj.Preview) + } + + for i, _ := range obj.Attachment { + WriteAttachmentToCache(db, obj.Attachment[i]) + WriteActivitytoCacheWithAttachment(db, obj, obj.Attachment[i], *obj.Preview) + } + + } else { + WriteActivitytoCache(db, obj) + } + + WriteObjectReplyToCache(db, obj) + + return obj +} + +func WriteActivitytoCache(db *sql.DB, obj ObjectBase) { + + obj.Name = EscapeString(obj.Name) + obj.Content = EscapeString(obj.Content) + obj.AttributedTo = EscapeString(obj.AttributedTo) + + query := `select id from cacheactivitystream where id=$1` + + rows, err := db.Query(query, obj.Id) + + CheckError(err, "error selecting obj id from cache") + + var id string + defer rows.Close() + rows.Next() + rows.Scan(&id) + + if id != "" { + return + } + + query = `insert into cacheactivitystream (id, type, name, content, published, updated, attributedto, actor) values ($1, $2, $3, $4, $5, $6, $7, $8)` + + _, e := db.Exec(query, obj.Id ,obj.Type, obj.Name, obj.Content, obj.Published, obj.Published, obj.AttributedTo, obj.Actor.Id) + + if e != nil{ + fmt.Println("error inserting new activity cache") + panic(e) + } +} + +func WriteActivitytoCacheWithAttachment(db *sql.DB, obj ObjectBase, attachment ObjectBase, preview NestedObjectBase) { + + obj.Name = EscapeString(obj.Name) + obj.Content = EscapeString(obj.Content) + obj.AttributedTo = EscapeString(obj.AttributedTo) + + query := `select id from cacheactivitystream where id=$1` + + rows, err := db.Query(query, obj.Id) + + CheckError(err, "error selecting activity with attachment obj id cache") + + var id string + defer rows.Close() + rows.Next() + rows.Scan(&id) + + if id != "" { + return + } + + query = `insert into cacheactivitystream (id, type, name, content, attachment, preview, published, updated, attributedto, actor) values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)` + + _, e := db.Exec(query, obj.Id ,obj.Type, obj.Name, obj.Content, attachment.Id, preview.Id, obj.Published, obj.Published, obj.AttributedTo, obj.Actor.Id) + + if e != nil{ + fmt.Println("error inserting new activity with attachment cache") + panic(e) + } +} + +func WriteAttachmentToCache(db *sql.DB, obj ObjectBase) { + + query := `select id from cacheactivitystream where id=$1` + + rows, err := db.Query(query, obj.Id) + + CheckError(err, "error selecting attachment obj id cache") + + var id string + defer rows.Close() + rows.Next() + rows.Scan(&id) + + if id != "" { + return + } + + query = `insert into cacheactivitystream (id, type, name, href, published, updated, attributedTo, mediatype, size) values ($1, $2, $3, $4, $5, $6, $7, $8, $9)` + + _, e := db.Exec(query, obj.Id ,obj.Type, obj.Name, obj.Href, obj.Published, obj.Published, obj.AttributedTo, obj.MediaType, obj.Size) + + if e != nil{ + fmt.Println("error inserting new attachment cache") + panic(e) + } +} + +func WritePreviewToCache(db *sql.DB, obj NestedObjectBase) { + + query := `select id from cacheactivitystream where id=$1` + + rows, err := db.Query(query, obj.Id) + + CheckError(err, "error selecting preview obj id cache") + + var id string + defer rows.Close() + rows.Next() + rows.Scan(&id) + + if id != "" { + return + } + + query = `insert into cacheactivitystream (id, type, name, href, published, updated, attributedTo, mediatype, size) values ($1, $2, $3, $4, $5, $6, $7, $8, $9)` + + _, e := db.Exec(query, obj.Id ,obj.Type, obj.Name, obj.Href, obj.Published, obj.Published, obj.AttributedTo, obj.MediaType, obj.Size) + + if e != nil{ + fmt.Println("error inserting new preview cache") + panic(e) + } +} + +func GetObjectFromCache(db *sql.DB, id string) Collection { + var nColl Collection + var result []ObjectBase + + query := `select id, name, content, type, published, updated, attributedto, attachment, preview, actor from cacheactivitystream where id=$1 and type='Note'` + + rows, err := db.Query(query, id) + + CheckError(err, "error query object from db cache") + + defer rows.Close() + for rows.Next(){ + var post ObjectBase + var actor Actor + var attachID string + var previewID string + + err = rows.Scan(&post.Id, &post.Name, &post.Content, &post.Type, &post.Published, &post.Updated, &post.AttributedTo, &attachID, &previewID, &actor.Id) + + CheckError(err, "error scan object into post struct cache") + + post.Actor = &actor + + var postCnt int + var imgCnt int + post.Replies, postCnt, imgCnt = GetObjectRepliesCache(db, post) + + post.Replies.TotalItems, post.Replies.TotalImgs = GetObjectRepliesCacheCount(db, post) + + post.Replies.TotalItems = post.Replies.TotalItems + postCnt + post.Replies.TotalImgs = post.Replies.TotalImgs + imgCnt + + post.Attachment = GetObjectAttachmentCache(db, attachID) + + post.Preview = GetObjectPreviewCache(db, previewID) + + result = append(result, post) + } + + nColl.OrderedItems = result + + return nColl +} + +func WriteObjectReplyToCache(db *sql.DB, obj ObjectBase) { + for i, e := range obj.InReplyTo { + if(i == 0 || IsReplyInThread(db, obj.InReplyTo[0].Id, e.Id)){ + + query := `select id from cachereplies where id=$1` + + rows, err := db.Query(query, obj.Id) + + CheckError(err, "error selecting obj id cache reply") + + var id string + defer rows.Close() + rows.Next() + rows.Scan(&id) + + if id != "" { + return + } + + query = `insert into cachereplies (id, inreplyto) values ($1, $2)` + + _, err = db.Exec(query, obj.Id, e.Id) + + if err != nil{ + fmt.Println("error inserting replies cache") + panic(err) + } + } + } +} + +func GetObjectRepliesCache(db *sql.DB, parent ObjectBase) (*CollectionBase, int, int) { + + var nColl CollectionBase + var result []ObjectBase + + query := `select id, name, content, type, published, attributedto, attachment, preview, actor from cacheactivitystream WHERE id in (select id from cachereplies where inreplyto=$1) and type='Note' order by published asc` + + rows, err := db.Query(query, parent.Id) + + CheckError(err, "error with replies db query") + + defer rows.Close() + for rows.Next() { + var post ObjectBase + var actor Actor + var attachID string + var previewID string + + post.InReplyTo = append(post.InReplyTo, parent) + + err = rows.Scan(&post.Id, &post.Name, &post.Content, &post.Type, &post.Published, &post.AttributedTo, &attachID, &previewID, &actor.Id) + + + CheckError(err, "error with replies db scan") + + post.Actor = &actor + + var postCnt int + var imgCnt int + post.Replies, postCnt, imgCnt = GetObjectRepliesRepliesCache(db, post) + + post.Replies.TotalItems, post.Replies.TotalImgs = GetObjectRepliesCacheCount(db, post) + + post.Replies.TotalItems = post.Replies.TotalItems + postCnt + post.Replies.TotalImgs = post.Replies.TotalImgs + imgCnt + + post.Attachment = GetObjectAttachmentCache(db, attachID) + + post.Preview = GetObjectPreviewCache(db, previewID) + + result = append(result, post) + } + + nColl.OrderedItems = result + + remoteCollection := GetObjectRepliesRemote(db, parent) + + var postc int + var imgc int + for _, e := range remoteCollection.OrderedItems { + nColl.OrderedItems = append(nColl.OrderedItems, e) + postc = postc + 1 + if len(e.Attachment) > 0 { + imgc = imgc + 1 + } + } + + return &nColl, postc, imgc +} + +func GetObjectRepliesRepliesCache(db *sql.DB, parent ObjectBase) (*CollectionBase, int, int) { + + var nColl CollectionBase + var result []ObjectBase + + query := `select id, name, content, type, published, attributedto, attachment, preview, actor from cacheactivitystream where id in (select id from cachereplies where inreplyto=$1) and type='Note' order by published asc` + + rows, err := db.Query(query, parent.Id) + + CheckError(err, "error with replies replies cache query") + + defer rows.Close() + for rows.Next() { + var post ObjectBase + var actor Actor + var attachID string + var previewID string + + post.InReplyTo = append(post.InReplyTo, parent) + + err = rows.Scan(&post.Id, &post.Name, &post.Content, &post.Type, &post.Published, &post.AttributedTo, &attachID, &previewID, &actor.Id) + + + CheckError(err, "error with replies replies cache scan") + + post.Actor = &actor + + post.Attachment = GetObjectAttachmentCache(db, attachID) + + post.Preview = GetObjectPreviewCache(db, previewID) + + result = append(result, post) + } + + remoteCollection := GetObjectRepliesRemote(db, parent) + + var postc int + var imgc int + for _, e := range remoteCollection.OrderedItems { + + nColl.OrderedItems = append(nColl.OrderedItems, e) + postc = postc + 1 + if len(e.Attachment) > 0 { + imgc = imgc + 1 + } + } + + nColl.OrderedItems = result + + return &nColl, postc, imgc +} + +func GetObjectRepliesCacheCount(db *sql.DB, parent ObjectBase) (int, int) { + + var countId int + var countImg int + + query := `select count(id) from replies where inreplyto=$1 and id in (select id from activitystream where type='Note')` + + rows, err := db.Query(query, parent.Id) + + CheckError(err, "error with replies count db query") + + defer rows.Close() + rows.Next() + rows.Scan(&countId) + + query = `select count(attachment) from activitystream where id in (select id from replies where inreplyto=$1) and attachment != ''` + + rows, err = db.Query(query, parent.Id) + + CheckError(err, "error with select attachment count db query") + + defer rows.Close() + rows.Next() + rows.Scan(&countImg) + + return countId, countImg +} + +func GetObjectAttachmentCache(db *sql.DB, id string) []ObjectBase { + + var attachments []ObjectBase + + query := `select id, type, name, href, mediatype, size, published from cacheactivitystream where id=$1` + + rows, err := db.Query(query, id) + + CheckError(err, "could not select object attachment query") + + defer rows.Close() + for rows.Next() { + var attachment = new(ObjectBase) + + err = rows.Scan(&attachment.Id, &attachment.Type, &attachment.Name, &attachment.Href, &attachment.MediaType, &attachment.Size, &attachment.Published) + if err !=nil{ + fmt.Println("error with attachment db query") + panic(err) + } + + attachments = append(attachments, *attachment) + } + + return attachments +} + +func GetObjectPreviewCache(db *sql.DB, id string) *NestedObjectBase { + + var preview NestedObjectBase + + query := `select id, type, name, href, mediatype, size, published from cacheactivitystream where id=$1` + + rows, err := db.Query(query, id) + + CheckError(err, "could not select object preview query") + + defer rows.Close() + for rows.Next() { + err = rows.Scan(&preview.Id, &preview.Type, &preview.Name, &preview.Href, &preview.MediaType, &preview.Size, &preview.Published) + } + + return &preview +} + +func DeleteObjectFromCache(db *sql.DB, id string) { + query := `select attachment, preview from cacheactivitystream where id=$1 ` + + rows, err := db.Query(query, id) + CheckError(err, "could not select cache activitystream") + + var attachment string + var preview string + + defer rows.Close() + rows.Next() + rows.Scan(&attachment, &preview) + + query = `delete from cacheactivitystream where id=$1` + _, err = db.Exec(query, attachment) + CheckError(err, "could not delete attachmet cache activitystream") + + query = `delete from cacheactivitystream where id=$1` + _, err = db.Exec(query, preview) + CheckError(err, "could not delete preview cache activitystream") + + query = `delete from cacheactivitystream where id=$1` + _, err = db.Exec(query, id) + CheckError(err, "could not delete object cache activitystream") + + query = `delete from cachereplies where id=$1` + _, err = db.Exec(query, id) + CheckError(err, "could not delete cache replies activitystream") +} + diff --git a/Database.go b/Database.go index bf6ff82..3b4dfc4 100644 --- a/Database.go +++ b/Database.go @@ -72,17 +72,23 @@ func CreateNewBoardDB(db *sql.DB, actor Actor) Actor{ CreateBoardMod(db, nverify) if actor.Name != "main" { - var nActivity Activity var nActor Actor var nObject ObjectBase + var nActivity Activity - nActor.Id = Domain - nObject.Id = actor.Id - + nActivity.AtContext.Context = "https://www.w3.org/ns/activitystreams" + nActivity.Type = "Follow" nActivity.Actor = &nActor nActivity.Object = &nObject - - SetActorFollowDB(db, nActivity, Domain) + nActivity.Actor.Id = Domain + var mActor Actor + nActivity.Object.Actor = &mActor + nActivity.Object.Actor.Id = actor.Id + nActivity.To = append(nActivity.To, actor.Id) + + response := AcceptFollow(nActivity) + SetActorFollowingDB(db, response) + MakeActivityRequest(nActivity) } } @@ -466,10 +472,17 @@ func GetObjectRepliesRemote(db *sql.DB, parent ObjectBase) CollectionBase { for rows.Next() { var id string rows.Scan(&id) - - coll := GetCollectionFromID(id) - for _, e := range coll.OrderedItems { + cacheColl := GetObjectFromCache(db, id) + + if len(cacheColl.OrderedItems) < 1 { + cacheColl = GetCollectionFromID(id) + for _, e := range cacheColl.OrderedItems { + WriteObjectToCache(db, e) + } + } + + for _, e := range cacheColl.OrderedItems { result = append(result, e) } } @@ -559,42 +572,6 @@ func GetObjectRepliesDBCount(db *sql.DB, parent ObjectBase) (int, int) { return countId, countImg } -func GetObjectRepliesRemoteCount(db *sql.DB, parent ObjectBase) (int, int) { - var nColl CollectionBase - var result []ObjectBase - query := `select id from replies where id not in (select id from activitystream) and inreplyto=$1` - - rows, err := db.Query(query, parent.Id) - - CheckError(err, "could not get remote id query") - - defer rows.Close() - for rows.Next() { - var id string - rows.Scan(&id) - - coll := GetCollectionFromID(id) - - for _, e := range coll.OrderedItems { - result = append(result, e) - } - } - - nColl.OrderedItems = result - - var posts int - var imgs int - - for _, e := range nColl.OrderedItems { - posts = posts + 1 - if len(e.Attachment) > 0 { - imgs = imgs + 1 - } - } - - return posts, imgs -} - func GetObjectAttachment(db *sql.DB, id string) []ObjectBase { var attachments []ObjectBase @@ -692,9 +669,7 @@ func DeletePreviewFromFile(db *sql.DB, id string) { var href string var _type string err := rows.Scan(&href, &_type) - fmt.Println(href) href = strings.Replace(href, Domain + "/", "", 1) - fmt.Println(href) CheckError(err, "error scanning delete attachment") if _type != "Tombstone" { @@ -852,6 +827,7 @@ func DeleteObject(db *sql.DB, id string) { DeleteAttachmentFromFile(db, id) DeletePreviewFromFile(db, id) DeleteObjectFromDB(db, id) + DeleteObjectRequest(db, id) } func DeleteObjectAndReplies(db *sql.DB, id string) { @@ -866,7 +842,8 @@ func DeleteObjectAndReplies(db *sql.DB, id string) { DeleteObjectRepliesFromDB(db, id) DeleteAttachmentRepliesFromDB(db, id) DeletePreviewRepliesFromDB(db, id) - DeleteObjectFromDB(db, id) + DeleteObjectFromDB(db, id) + DeleteObjectAndRepliesRequest(db, id) } func GetRandomCaptcha(db *sql.DB) string{ @@ -1007,3 +984,5 @@ func GetActorReportedDB(db *sql.DB, id string) []ObjectBase { return nObj } + + @@ -11,7 +11,7 @@ func GetActorFollowing(w http.ResponseWriter, db *sql.DB, id string) { following.AtContext.Context = "https://www.w3.org/ns/activitystreams" following.Type = "Collection" following.TotalItems, _ = GetActorFollowTotal(db, id) - following.Items, _ = GetActorFollowDB(db, id) + following.Items = GetActorFollowingDB(db, id) enc, _ := json.MarshalIndent(following, "", "\t") w.Header().Set("Content-Type", "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"") @@ -24,57 +24,16 @@ func GetActorFollowers(w http.ResponseWriter, db *sql.DB, id string) { following.AtContext.Context = "https://www.w3.org/ns/activitystreams" following.Type = "Collection" _, following.TotalItems = GetActorFollowTotal(db, id) - _, following.Items = GetActorFollowDB(db, id) + following.Items = GetActorFollowDB(db, id) enc, _ := json.MarshalIndent(following, "", "\t") w.Header().Set("Content-Type", "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"") w.Write(enc) } -func SetActorFollowDB(db *sql.DB, activity Activity, actor string) Activity { - var query string - alreadyFollow := false - following, follower := GetActorFollowDB(db, actor) - - if activity.Actor.Id == actor { - for _, e := range following { - if e.Id == activity.Object.Id { - alreadyFollow = true - } - } - if alreadyFollow { - query = `delete from following where id=$1 and following=$2` - activity.Summary = activity.Actor.Id + " Unfollow " + activity.Object.Id - } else { - query = `insert into following (id, following) values ($1, $2)` - activity.Summary = activity.Actor.Id + " Follow " + activity.Object.Id - } - } else { - for _, e := range follower { - if e.Id == activity.Actor.Id { - alreadyFollow = true - } - } - if alreadyFollow { - query = `delete from follower where id=$1 and follower=$2` - activity.Summary = activity.Actor.Id + " Unfollow " + activity.Object.Id - } else { - query = `insert into follower (id, follower) values ($1, $2)` - activity.Summary = activity.Actor.Id + " Follow " + activity.Object.Id - } - } - - _, err := db.Exec(query, activity.Actor.Id, activity.Object.Id) - CheckError(err, "error with follow db insert/delete") - - return activity -} - -func GetActorFollowDB(db *sql.DB, id string) ([]ObjectBase, []ObjectBase) { +func GetActorFollowingDB(db *sql.DB, id string) []ObjectBase { var followingCollection []ObjectBase - var followerCollection []ObjectBase - query := `select following from following where id=$1` rows, err := db.Query(query, id) @@ -93,11 +52,17 @@ func GetActorFollowDB(db *sql.DB, id string) ([]ObjectBase, []ObjectBase) { followingCollection = append(followingCollection, obj) } - query = `select follower from follower where id=$1` + return followingCollection +} - rows, err = db.Query(query, id) +func GetActorFollowDB(db *sql.DB, id string) []ObjectBase { + var followerCollection []ObjectBase - CheckError(err, "error with followers db query") + query := `select follower from follower where id=$1` + + rows, err := db.Query(query, id) + + CheckError(err, "error with follower db query") defer rows.Close() @@ -111,7 +76,7 @@ func GetActorFollowDB(db *sql.DB, id string) ([]ObjectBase, []ObjectBase) { followerCollection = append(followerCollection, obj) } - return followingCollection, followerCollection + return followerCollection } func GetActorFollowTotal(db *sql.DB, id string) (int, int) { @@ -149,69 +114,100 @@ func GetActorFollowTotal(db *sql.DB, id string) (int, int) { return following, followers } -func AcceptFollow(activity Activity, actor Actor) Activity { +func AcceptFollow(activity Activity) Activity { var accept Activity - var obj ObjectBase - - obj.Type = activity.Type - obj.Actor = activity.Actor - - var nobj NestedObjectBase - obj.Object = &nobj - obj.Object.Id = activity.Object.Id - accept.AtContext.Context = activity.AtContext.Context accept.Type = "Accept" - - var nactor Actor - accept.Actor = &nactor - accept.Actor.Id = actor.Id - accept.Object = &obj - accept.To = append(accept.To, activity.Object.Id) + accept.Actor = activity.Object.Actor + var nObj ObjectBase + var nActor Actor + accept.Object = &nObj + accept.Object.Actor = &nActor + accept.Object.Actor = activity.Actor + var nNested NestedObjectBase + var mActor Actor + accept.Object.Object = &nNested + accept.Object.Object.Actor = &mActor + accept.Object.Object.Actor = activity.Object.Actor + accept.Object.Object.Type = "Follow" + accept.To = append(accept.To, activity.Object.Actor.Id) return accept } -func RejectFollow(activity Activity, actor Actor) Activity { +func RejectFollow(activity Activity) Activity { var accept Activity - var obj ObjectBase - - obj.Type = activity.Type - obj.Actor = activity.Actor - obj.Object = new(NestedObjectBase) - obj.Object.Id = activity.Object.Id - accept.AtContext.Context = activity.AtContext.Context accept.Type = "Reject" - accept.Actor = &actor - accept.Object = &obj + var nObj ObjectBase + var nActor Actor + accept.Object = &nObj + accept.Object.Actor = &nActor + accept.Actor = activity.Object.Actor + accept.Object.Actor = activity.Actor + var nNested NestedObjectBase + var mActor Actor + accept.Object.Object = &nNested + accept.Object.Object.Actor = &mActor + accept.Object.Object.Actor = activity.Object.Actor + accept.Object.Object.Type = "Follow" + accept.To = append(accept.To, activity.Actor.Id) + + return accept +} - return accept +func SetActorFollowerDB(db *sql.DB, activity Activity) Activity { + var query string + alreadyFollow := false + followers := GetActorFollowDB(db, activity.Actor.Id) + + for _, e := range followers { + if e.Id == activity.Object.Actor.Id { + alreadyFollow = true + } + } + if alreadyFollow { + query = `delete from follower where id=$1 and follower=$2` + activity.Summary = activity.Object.Actor.Id + " Unfollow " + activity.Actor.Id + } else { + query = `insert into follower (id, follower) values ($1, $2)` + activity.Summary = activity.Object.Actor.Id + " Follow " + activity.Actor.Id + } + + _, err := db.Exec(query, activity.Actor.Id, activity.Object.Actor.Id) + + if CheckError(err, "error with follower db insert/delete") != nil { + activity.Type = "Reject" + return activity + } + + activity.Type = "Accept" + return activity } -func SetActorFollowingDB(db *sql.DB, activity Activity) Activity{ +func SetActorFollowingDB(db *sql.DB, activity Activity) Activity { var query string alreadyFollow := false - _, follower := GetActorFollowDB(db, activity.Object.Id) + following := GetActorFollowingDB(db, activity.Object.Actor.Id) - for _, e := range follower { - if e.Id == activity.Object.Id { + + for _, e := range following { + if e.Id == activity.Actor.Id { alreadyFollow = true } } if alreadyFollow { - query = `delete from follower where id=$1 and follower=$2` - activity.Summary = activity.Actor.Id + " Unfollow " + activity.Object.Id + query = `delete from following where id=$1 and following=$2` + activity.Summary = activity.Object.Actor.Id + " Unfollowing " + activity.Actor.Id } else { - query = `insert into follower (id, follower) values ($1, $2)` - activity.Summary = activity.Actor.Id + " Follow " + activity.Object.Id + query = `insert into following (id, following) values ($1, $2)` + activity.Summary = activity.Object.Actor.Id + " Following " + activity.Actor.Id } - _, err := db.Exec(query, activity.Object.Id, activity.Actor.Id) + _, err := db.Exec(query, activity.Object.Actor.Id, activity.Actor.Id) - if err != nil { - CheckError(err, "error with follow db insert/delete") + if CheckError(err, "error with following db insert/delete") != nil { activity.Type = "Reject" return activity } diff --git a/OutboxPost.go b/OutboxPost.go index dacf77e..84810c9 100644 --- a/OutboxPost.go +++ b/OutboxPost.go @@ -38,36 +38,18 @@ func ParseOutboxRequest(w http.ResponseWriter, r *http.Request, db *sql.DB) { w.Write([]byte("file type not supported")) return } - } var nObj = CreateObject("Note") nObj = ObjectFromForm(r, db, nObj) - + var act Actor nObj.Actor = &act nObj.Actor.Id = Domain + "/" + actor.Name - delete := regexp.MustCompile("delete:.+") - for _, e := range nObj.Option { - if delete.MatchString(e) { - verification := strings.Replace(e, "delete:", "", 1) - if HasAuth(db, verification, Domain + "/" + actor.Name) { - for _, e := range nObj.InReplyTo { - if IsObjectLocal(db, e.Id) && e.Id != nObj.InReplyTo[len(nObj.InReplyTo) - 1].Id { - DeleteObject(db, e.Id) - nObj.Type = "Delete" - } - } - } - } - } - - if nObj.Type != "Delete" { - nObj = writeObjectToDB(db, nObj) - activity := CreateActivity("Create", nObj) - MakeActivityRequest(activity) - } + nObj = writeObjectToDB(db, nObj) + activity := CreateActivity("Create", nObj) + MakeActivityRequest(activity) var id string re := regexp.MustCompile("\\w+$") @@ -82,9 +64,14 @@ func ParseOutboxRequest(w http.ResponseWriter, r *http.Request, db *sql.DB) { w.WriteHeader(http.StatusOK) w.Write([]byte(id)) + return } + + w.WriteHeader(http.StatusForbidden) + w.Write([]byte("could not authenticate")) } else { activity = GetActivityFromJson(r, db) + if IsActivityLocal(db, activity) { switch activity.Type { case "Create": @@ -102,46 +89,56 @@ func ParseOutboxRequest(w http.ResponseWriter, r *http.Request, db *sql.DB) { var validActor bool var validLocalActor bool - _, validActor = IsValidActor(activity.Object.Id) - validLocalActor = (activity.Actor.Id == actor.Id) || (activity.Object.Id == actor.Id) - verification := GetVerificationByCode(db, activity.Auth) + header := r.Header.Get("Authorization") - var rActivity Activity - fmt.Println("ok") - if validActor && validLocalActor && verification.Board == activity.Actor.Id || verification.Board == Domain { - fmt.Println("yes") - rActivity = AcceptFollow(activity, actor) - } else { - fmt.Println("no") - rActivity = RejectFollow(activity, actor) - rActivity.Summary = "No valid actor or Actor is not located here" - } + auth := strings.Split(header, " ") - if rActivity.Type == "Accept" { - rActivity.Summary = SetActorFollowDB(db, activity, actor.Id).Summary + if len(auth) < 2 { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte("")) + return } + + _, validActor = IsValidActor(activity.Object.Actor.Id) + validLocalActor = (activity.Actor.Id == actor.Id) + verification := GetVerificationByCode(db, auth[1]) - enc, _ := json.MarshalIndent(rActivity, "", "\t") - - if rActivity.Type == "Reject" { - w.WriteHeader(http.StatusBadRequest) + var rActivity Activity + if validActor && validLocalActor && verification.Board == activity.Actor.Id || verification.Board == Domain { + rActivity = AcceptFollow(activity) + SetActorFollowingDB(db, rActivity) + MakeActivityRequest(activity) } - - w.Header().Set("Content-Type", "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"") - w.Write(enc) - + w.Write([]byte("")) case "Delete": fmt.Println("This is a delete") w.WriteHeader(http.StatusBadRequest) w.Write([]byte("could not process activity")) case "Note": - fmt.Println("This is a note") w.WriteHeader(http.StatusBadRequest) w.Write([]byte("could not process activity")) case "New": - fmt.Println("Added new Board") + + header := r.Header.Get("Authorization") + + auth := strings.Split(header, " ") + + if len(auth) < 2 { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte("")) + return + } + + verification := GetVerificationByCode(db, auth[1]) + + if verification.Board != Domain { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte("")) + return + } + name := activity.Object.Actor.Name prefname := activity.Object.Actor.PreferredUsername summary := activity.Object.Actor.Summary @@ -163,6 +160,7 @@ func ParseOutboxRequest(w http.ResponseWriter, r *http.Request, db *sql.DB) { w.Write([]byte("could not process activity")) } } else { + fmt.Println("is NOT activity") w.WriteHeader(http.StatusBadRequest) w.Write([]byte("could not process activity")) @@ -319,7 +317,7 @@ func HasContextFromJson(context []byte) bool { err = json.Unmarshal(context, &arrContext.Context) CheckError(err, "error with string") if arrContext.Context == "https://www.w3.org/ns/activitystreams" { - hasContext = true + hasContext = true } } @@ -517,15 +515,37 @@ func ParseInboxRequest(w http.ResponseWriter, r *http.Request, db *sql.DB) { } break + case "Delete": + for _, e := range activity.To { + actor := GetActorFromDB(db, e) + if actor.Id != "" { + DeleteObjectFromCache(db, activity.Object.Id) + return + } + } + break + + case "Follow": for _, e := range activity.To { - if IsObjectLocal(db, e) { - nActivity := SetActorFollowingDB(db, activity) - j, _ := json.Marshal(&nActivity) - w.Write([]byte(j)) + if GetActorFromDB(db, e).Id != "" { + response := AcceptFollow(activity) + response = SetActorFollowerDB(db, response) + MakeActivityRequest(response) + } else { + fmt.Println("follow request for rejected") + response := RejectFollow(activity) + MakeActivityRequest(response) } } break + + case "Reject": + if activity.Object.Object.Type == "Follow" { + fmt.Println("follow rejected") + SetActorFollowingDB(db, activity) + } + break } } diff --git a/databaseschema.psql b/databaseschema.psql index e4c3fe1..d2544cc 100644 --- a/databaseschema.psql +++ b/databaseschema.psql @@ -132,4 +132,76 @@ formerType varchar(100) default '', size int default NULL, public boolean default false, CONSTRAINT fk_object FOREIGN KEY (object) REFERENCES activitystream(id) +); + +CREATE TABLE IF NOT EXISTS cachereplies( +id varchar(100), +inreplyto varchar(100) +); + +CREATE TABLE IF NOT EXISTS cacheactivitystream( +actor varchar(100) default '', +attachment varchar(100) default '', +attributedTo varchar(100) default '', +audience varchar(100) default '', +bcc varchar(100) default '', +bto varchar(100) default '', +cc varchar(100) default '', +context varchar(100) default '', +current varchar(100) default '', +first varchar(100) default '', +generator varchar(100) default '', +icon varchar(100) default '', +id varchar(100) UNIQUE PRIMARY KEY, +image varchar(100) default '', +instrument varchar(100) default '', +last varchar(100) default '', +location varchar(100) default '', +items varchar(100) default '', +oneOf varchar(100) default '', +anyOf varchar(100) default '', +closed varchar(100) default '', +origin varchar(100) default '', +next varchar(100) default '', +object varchar(100), +prev varchar(100) default '', +preview varchar(100) default '', +result varchar(100) default '', +tag varchar(100) default '', +target varchar(100) default '', +type varchar(100) default '', +to_ varchar(100) default '', +url varchar(100) default '', +accuracy varchar(100) default '', +altitude varchar(100) default '', +content varchar(2000) default '', +name varchar(100) default '', +alias varchar(100) default '', +duration varchar(100) default '', +height varchar(100) default '', +href varchar(100) default '', +hreflang varchar(100) default '', +partOf varchar(100) default '', +latitude varchar(100) default '', +longitude varchar(100) default '', +mediaType varchar(100) default '', +endTime varchar(100) default '', +published TIMESTAMP default NOW(), +startTime varchar(100) default '', +radius varchar(100) default '', +rel varchar(100) default '', +startIndex varchar(100) default '', +summary varchar(100) default '', +totalItems varchar(100) default '', +units varchar(100) default '', +updated TIMESTAMP default NOW(), +deleted TIMESTAMP default NULL, +width varchar(100) default '', +subject varchar(100) default '', +relationship varchar(100) default '', +describes varchar(100) default '', +formerType varchar(100) default '', +size int default NULL, +public boolean default false, +CONSTRAINT fk_object FOREIGN KEY (object) REFERENCES cacheactivitystream(id) );
\ No newline at end of file @@ -701,7 +701,7 @@ func CheckValidActivity(id string) (Collection, bool) { func GetActor(id string) Actor { - var respActor Actor + var respActor Actor req, err := http.NewRequest("GET", id, nil) @@ -747,7 +747,6 @@ func GetActorCollection(collection string) Collection { return nCollection } - func IsValidActor(id string) (Actor, bool) { var respCollection Actor req, err := http.NewRequest("GET", id, nil) @@ -969,7 +968,7 @@ func MakeActivityRequest(activity Activity) { j, _ := json.MarshalIndent(activity, "", "\t") for _, e := range activity.To { actor := GetActor(e) - + req, err := http.NewRequest("POST", actor.Inbox, bytes.NewBuffer(j)) CheckError(err, "error with sending activity req to") @@ -994,13 +993,16 @@ func GetCollectionFromID(id string) Collection { return nColl } - defer resp.Body.Close() - - body, _ := ioutil.ReadAll(resp.Body) + if resp.StatusCode == 200 { + defer resp.Body.Close() + + body, _ := ioutil.ReadAll(resp.Body) - err = json.Unmarshal(body, &nColl) + err = json.Unmarshal(body, &nColl) - CheckError(err, "error getting collection resp from json body") + CheckError(err, "error getting collection resp from json body") + + } return nColl } @@ -1088,3 +1090,41 @@ func GetUniqueFilename(_type string) string { return "" } + +func DeleteObjectRequest(db *sql.DB, id string) { + var nObj ObjectBase + nObj.Id = id + + activity := CreateActivity("Delete", nObj) + + obj := GetObjectFromPath(db, id) + followers := GetActorFollowDB(db, obj.Actor.Id) + for _, e := range followers { + activity.To = append(activity.To, e.Id) + } + + following := GetActorFollowingDB(db, obj.Actor.Id) + for _, e := range following { + activity.To = append(activity.To, e.Id) + } + + MakeActivityRequest(activity) +} + +func DeleteObjectAndRepliesRequest(db *sql.DB, id string) { + var nObj ObjectBase + nObj.Id = id + + activity := CreateActivity("Delete", nObj) + + obj := GetObjectFromPath(db, id) + + followers := GetActorFollowDB(db, obj.Actor.Id) + for _, e := range followers { + activity.To = append(activity.To, e.Id) + } + + MakeActivityRequest(activity) +} + + diff --git a/outboxGet.go b/outboxGet.go index 1065ad9..7aaf70f 100644 --- a/outboxGet.go +++ b/outboxGet.go @@ -23,8 +23,6 @@ func GetActorOutbox(w http.ResponseWriter, r *http.Request, db *sql.DB) { w.Write(enc) } - - func GetObjectsFromFollow(actor Actor) []ObjectBase { var followingCol Collection var followObj []ObjectBase @@ -107,9 +105,12 @@ func GetObjectFromPath(db *sql.DB, path string) ObjectBase{ for rows.Next(){ var post ObjectBase var attachID string - var previewID string + var previewID string + + var nActor Actor + post.Actor = &nActor - err = rows.Scan(&post.Id, &post.Name, &post.Content, &post.Type, &post.Published, &post.AttributedTo, &attachID, &previewID, &post.Actor) + err = rows.Scan(&post.Id, &post.Name, &post.Content, &post.Type, &post.Published, &post.AttributedTo, &attachID, &previewID, &post.Actor.Id) CheckError(err, "error scan object into post struct from path") |