aboutsummaryrefslogtreecommitdiff
path: root/db/database.go
diff options
context:
space:
mode:
Diffstat (limited to 'db/database.go')
-rw-r--r--db/database.go584
1 files changed, 144 insertions, 440 deletions
diff --git a/db/database.go b/db/database.go
index 5d53f46..c6c2fc7 100644
--- a/db/database.go
+++ b/db/database.go
@@ -2,11 +2,9 @@ package db
import (
"database/sql"
- "encoding/json"
"fmt"
"html/template"
"io/ioutil"
- "net/http"
"os"
"regexp"
"strings"
@@ -15,7 +13,6 @@ import (
"github.com/FChannel0/FChannel-Server/activitypub"
"github.com/FChannel0/FChannel-Server/config"
"github.com/FChannel0/FChannel-Server/util"
- "github.com/FChannel0/FChannel-Server/webfinger"
_ "github.com/lib/pq"
)
@@ -25,8 +22,7 @@ type NewsItem struct {
Time int
}
-// ConnectDB connects to the PostgreSQL database configured.
-func ConnectDB() error {
+func Connect() error {
host := config.DBHost
port := config.DBPort
user := config.DBUser
@@ -37,89 +33,98 @@ func ConnectDB() error {
"dbname=%s sslmode=disable", host, port, user, password, dbname)
_db, err := sql.Open("postgres", psqlInfo)
+
if err != nil {
- return err
+ return util.MakeError(err, "Connect")
}
if err := _db.Ping(); err != nil {
- return err
+ return util.MakeError(err, "Connect")
}
- fmt.Println("Successfully connected DB")
+ config.Log.Println("Successfully connected DB")
config.DB = _db
+
return nil
}
-// Close closes the database connection.
func Close() error {
- return config.DB.Close()
+ err := config.DB.Close()
+
+ return util.MakeError(err, "Close")
}
func RunDatabaseSchema() error {
query, err := ioutil.ReadFile("databaseschema.psql")
if err != nil {
- return err
+ return util.MakeError(err, "RunDatabaseSchema")
}
_, err = config.DB.Exec(string(query))
- return err
+ return util.MakeError(err, "RunDatabaseSchema")
}
-func CreateNewBoardDB(actor activitypub.Actor) (activitypub.Actor, error) {
- query := `insert into actor (type, id, name, preferedusername, inbox, outbox, following, followers, summary, restricted) values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`
+func CreateNewBoard(actor activitypub.Actor) (activitypub.Actor, error) {
+ if _, err := activitypub.GetActorFromDB(actor.Id); err == nil {
+ return activitypub.Actor{}, util.MakeError(err, "CreateNewBoardDB")
+ } else {
+ query := `insert into actor (type, id, name, preferedusername, inbox, outbox, following, followers, summary, restricted) values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`
+ _, err := config.DB.Exec(query, actor.Type, actor.Id, actor.Name, actor.PreferredUsername, actor.Inbox, actor.Outbox, actor.Following, actor.Followers, actor.Summary, actor.Restricted)
- _, err := config.DB.Exec(query, actor.Type, actor.Id, actor.Name, actor.PreferredUsername, actor.Inbox, actor.Outbox, actor.Following, actor.Followers, actor.Summary, actor.Restricted)
+ if err != nil {
+ return activitypub.Actor{}, util.MakeError(err, "CreateNewBoardDB")
+ }
- if err != nil {
- // TODO: board exists error
- return activitypub.Actor{}, err
- } else {
- fmt.Println("board added")
+ config.Log.Println("board added")
for _, e := range actor.AuthRequirement {
query = `insert into actorauth (type, board) values ($1, $2)`
-
if _, err := config.DB.Exec(query, e, actor.Name); err != nil {
- return activitypub.Actor{}, err
+ return activitypub.Actor{}, util.MakeError(err, "CreateNewBoardDB")
}
}
- var verify Verify
+ var verify util.Verify
- verify.Identifier = actor.Id
- verify.Code = util.CreateKey(50)
verify.Type = "admin"
-
- CreateVerification(verify)
-
verify.Identifier = actor.Id
- verify.Code = util.CreateKey(50)
- verify.Type = "janitor"
- CreateVerification(verify)
+ if verify.Code, err = util.CreateKey(50); err != nil {
+ return activitypub.Actor{}, util.MakeError(err, "CreateNewBoardDB")
+ }
+
+ if err := verify.Create(); err != nil {
+ return activitypub.Actor{}, util.MakeError(err, "CreateNewBoardDB")
+ }
+ verify.Type = "janitor"
verify.Identifier = actor.Id
- verify.Code = util.CreateKey(50)
- verify.Type = "post"
- CreateVerification(verify)
+ if verify.Code, err = util.CreateKey(50); err != nil {
+ return activitypub.Actor{}, util.MakeError(err, "CreateNewBoardDB")
+ }
+
+ if err := verify.Create(); err != nil {
+ return activitypub.Actor{}, util.MakeError(err, "CreateNewBoardDB")
+ }
- var nverify Verify
+ var nverify util.Verify
nverify.Board = actor.Id
nverify.Identifier = "admin"
nverify.Type = "admin"
- CreateBoardMod(nverify)
+
+ if err := nverify.CreateBoardMod(); err != nil {
+ return activitypub.Actor{}, util.MakeError(err, "CreateNewBoardDB")
+ }
nverify.Board = actor.Id
nverify.Identifier = "janitor"
nverify.Type = "janitor"
- CreateBoardMod(nverify)
- nverify.Board = actor.Id
- nverify.Identifier = "post"
- nverify.Type = "post"
- CreateBoardMod(nverify)
+ if err := nverify.CreateBoardMod(); err != nil {
+ return activitypub.Actor{}, util.MakeError(err, "CreateNewBoardDB")
+ }
activitypub.CreatePem(actor)
@@ -128,165 +133,90 @@ func CreateNewBoardDB(actor activitypub.Actor) (activitypub.Actor, error) {
var nActivity activitypub.Activity
nActor, err := activitypub.GetActorFromDB(config.Domain)
+
if err != nil {
- return actor, err
+ return actor, util.MakeError(err, "CreateNewBoardDB")
}
nActivity.AtContext.Context = "https://www.w3.org/ns/activitystreams"
nActivity.Type = "Follow"
nActivity.Actor = &nActor
nActivity.Object = &nObject
-
mActor, err := activitypub.GetActorFromDB(actor.Id)
+
if err != nil {
- return actor, err
+ return actor, util.MakeError(err, "CreateNewBoardDB")
}
nActivity.Object.Actor = mActor.Id
nActivity.To = append(nActivity.To, actor.Id)
- response := AcceptFollow(nActivity)
- if _, err := SetActorFollowingDB(response); err != nil {
- return actor, err
+ activityRequest := nActivity.AcceptFollow()
+
+ if _, err := activityRequest.SetActorFollowing(); err != nil {
+ return actor, util.MakeError(err, "CreateNewBoardDB")
}
- if err := MakeActivityRequest(nActivity); err != nil {
- return actor, err
+
+ if err := activityRequest.MakeRequestInbox(); err != nil {
+ return actor, util.MakeError(err, "CreateNewBoardDB")
}
}
-
}
return actor, nil
}
func RemovePreviewFromFile(id string) error {
+ var href string
+
query := `select href from activitystream where id in (select preview from activitystream where id=$1)`
- rows, err := config.DB.Query(query, id)
- if err != nil {
- return err
+ if err := config.DB.QueryRow(query, id).Scan(&href); err != nil {
+ return nil
}
- defer rows.Close()
- for rows.Next() {
- var href string
+ href = strings.Replace(href, config.Domain+"/", "", 1)
- if err := rows.Scan(&href); err != nil {
- return err
+ if href != "static/notfound.png" {
+ if _, err := os.Stat(href); err != nil {
+ return util.MakeError(err, "RemovePreviewFromFile")
}
- href = strings.Replace(href, config.Domain+"/", "", 1)
-
- if href != "static/notfound.png" {
- _, err = os.Stat(href)
- if err == nil {
- return os.Remove(href)
- }
- return err
- }
+ err := os.Remove(href)
+ return util.MakeError(err, "RemovePreviewFromFile")
}
obj := activitypub.ObjectBase{Id: id}
- return obj.DeletePreview()
-}
-
-func GetRandomCaptcha() (string, error) {
- var verify string
-
- query := `select identifier from verification where type='captcha' order by random() limit 1`
-
- rows, err := config.DB.Query(query)
- if err != nil {
- return verify, err
- }
- defer rows.Close()
-
- rows.Next()
- if err := rows.Scan(&verify); err != nil {
- return verify, err
- }
-
- return verify, nil
-}
-
-func GetCaptchaTotal() (int, error) {
- query := `select count(*) from verification where type='captcha'`
-
- rows, err := config.DB.Query(query)
- if err != nil {
- return 0, err
- }
-
- defer rows.Close()
-
- var count int
- for rows.Next() {
- if err := rows.Scan(&count); err != nil {
- return count, err
- }
- }
-
- return count, nil
-}
-
-func GetCaptchaCodeDB(verify string) (string, error) {
- query := `select code from verification where identifier=$1 limit 1`
-
- rows, err := config.DB.Query(query, verify)
- if err != nil {
- return "", err
- }
- defer rows.Close()
-
- var code string
-
- rows.Next()
- if err := rows.Scan(&code); err != nil {
- fmt.Println("Could not get verification captcha")
- }
-
- return code, nil
-}
-
-func DeleteCaptchaCodeDB(verify string) error {
- query := `delete from verification where identifier=$1`
-
- _, err := config.DB.Exec(query, verify)
- if err != nil {
- return err
- }
-
- return os.Remove("./" + verify)
+ err := obj.DeletePreview()
+ return util.MakeError(err, "RemovePreviewFromFile")
}
//if limit less than 1 return all news items
-func GetNewsFromDB(limit int) ([]NewsItem, error) {
+func GetNews(limit int) ([]NewsItem, error) {
var news []NewsItem
-
var query string
- if limit > 0 {
- query = `select title, content, time from newsItem order by time desc limit $1`
- } else {
- query = `select title, content, time from newsItem order by time desc`
- }
var rows *sql.Rows
var err error
+
if limit > 0 {
+ query = `select title, content, time from newsItem order by time desc limit $1`
rows, err = config.DB.Query(query, limit)
} else {
+ query = `select title, content, time from newsItem order by time desc`
rows, err = config.DB.Query(query)
}
if err != nil {
- return news, nil
+ return news, util.MakeError(err, "GetNews")
}
defer rows.Close()
for rows.Next() {
- n := NewsItem{}
var content string
+ n := NewsItem{}
+
if err := rows.Scan(&n.Title, &content, &n.Time); err != nil {
- return news, err
+ return news, util.MakeError(err, "GetNews")
}
content = strings.ReplaceAll(content, "\n", "<br>")
@@ -298,21 +228,13 @@ func GetNewsFromDB(limit int) ([]NewsItem, error) {
return news, nil
}
-func GetNewsItemFromDB(timestamp int) (NewsItem, error) {
+func GetNewsItem(timestamp int) (NewsItem, error) {
var news NewsItem
var content string
- query := `select title, content, time from newsItem where time=$1 limit 1`
-
- rows, err := config.DB.Query(query, timestamp)
- if err != nil {
- return news, err
- }
-
- defer rows.Close()
- rows.Next()
- if err := rows.Scan(&news.Title, &content, &news.Time); err != nil {
- return news, err
+ query := `select title, content, time from newsItem where time=$1 limit 1`
+ if err := config.DB.QueryRow(query, timestamp).Scan(&news.Title, &content, &news.Time); err != nil {
+ return news, util.MakeError(err, "GetNewsItem")
}
content = strings.ReplaceAll(content, "\n", "<br>")
@@ -321,65 +243,54 @@ func GetNewsItemFromDB(timestamp int) (NewsItem, error) {
return news, nil
}
-func deleteNewsItemFromDB(timestamp int) error {
+func DeleteNewsItem(timestamp int) error {
query := `delete from newsItem where time=$1`
_, err := config.DB.Exec(query, timestamp)
- return err
+
+ return util.MakeError(err, "DeleteNewsItem")
}
-func WriteNewsToDB(news NewsItem) error {
+func WriteNews(news NewsItem) error {
query := `insert into newsItem (title, content, time) values ($1, $2, $3)`
-
_, err := config.DB.Exec(query, news.Title, news.Content, time.Now().Unix())
- return err
-}
-
-func AddInstanceToInactiveDB(instance string) error {
- query := `select timestamp from inactive where instance=$1`
- rows, err := config.DB.Query(query, instance)
- if err != nil {
- return err
- }
+ return util.MakeError(err, "WriteNews")
+}
+func AddInstanceToInactive(instance string) error {
var timeStamp string
- defer rows.Close()
- rows.Next()
- rows.Scan(&timeStamp)
- if timeStamp == "" {
+ query := `select timestamp from inactive where instance=$1`
+ if err := config.DB.QueryRow(query, instance).Scan(&timeStamp); err != nil {
query := `insert into inactive (instance, timestamp) values ($1, $2)`
-
_, err := config.DB.Exec(query, instance, time.Now().UTC().Format(time.RFC3339))
- return err
+
+ return util.MakeError(err, "AddInstanceToInactive")
}
if !IsInactiveTimestamp(timeStamp) {
return nil
}
- query = `delete from following where following like $1`
- if _, err := config.DB.Exec(query, "%"+instance+"%"); err != nil {
- return err
- }
-
query = `delete from follower where follower like $1`
- if _, err = config.DB.Exec(query, "%"+instance+"%"); err != nil {
- return err
+ if _, err := config.DB.Exec(query, "%"+instance+"%"); err != nil {
+ return util.MakeError(err, "AddInstanceToInactive")
}
- return DeleteInstanceFromInactiveDB(instance)
+ err := DeleteInstanceFromInactive(instance)
+ return util.MakeError(err, "AddInstanceToInactive")
}
-func DeleteInstanceFromInactiveDB(instance string) error {
+func DeleteInstanceFromInactive(instance string) error {
query := `delete from inactive where instance=$1`
-
_, err := config.DB.Exec(query, instance)
- return err
+
+ return util.MakeError(err, "DeleteInstanceFromInactive")
}
func IsInactiveTimestamp(timeStamp string) bool {
stamp, _ := time.Parse(time.RFC3339, timeStamp)
+
if time.Now().UTC().Sub(stamp).Hours() > 48 {
return true
}
@@ -387,45 +298,9 @@ func IsInactiveTimestamp(timeStamp string) bool {
return false
}
-func ArchivePosts(actor activitypub.Actor) error {
- if actor.Id != "" && actor.Id != config.Domain {
- col, err := actor.GetAllArchive(165)
- if err != nil {
- return err
- }
-
- for _, e := range col.OrderedItems {
- for _, k := range e.Replies.OrderedItems {
- if err := k.UpdateType("Archive"); err != nil {
- return err
- }
- }
-
- if err := e.UpdateType("Archive"); err != nil {
- return err
- }
- }
- }
-
- return nil
-}
-
-func IsReplyInThread(inReplyTo string, id string) (bool, error) {
- obj, _, err := webfinger.CheckValidActivity(inReplyTo)
- if err != nil {
- return false, err
- }
-
- for _, e := range obj.OrderedItems[0].Replies.OrderedItems {
- if e.Id == id {
- return true, nil
- }
- }
-
- return false, nil
-}
-
func IsReplyToOP(op string, link string) (string, bool, error) {
+ var id string
+
if op == link {
return link, true, nil
}
@@ -440,52 +315,22 @@ func IsReplyToOP(op string, link string) (string, bool, error) {
}
query := `select id from replies where id like $1 and inreplyto=$2`
-
- rows, err := config.DB.Query(query, link, op)
- if err != nil {
- return op, false, err
- }
-
- defer rows.Close()
-
- var id string
- rows.Next()
- if err := rows.Scan(&id); err != nil {
- return id, false, err
+ if err := config.DB.QueryRow(query, link, op).Scan(&id); err != nil {
+ return op, false, nil
}
return id, id != "", nil
}
func GetReplyOP(link string) (string, error) {
- query := `select id from replies where id in (select inreplyto from replies where id=$1) and inreplyto=''`
-
- rows, err := config.DB.Query(query, link)
- if err != nil {
- return "", err
- }
- defer rows.Close()
-
var id string
- rows.Next()
- err = rows.Scan(&id)
- return id, err
-}
-
-func StartupArchive() error {
- for _, e := range webfinger.FollowingBoards {
- actor, err := activitypub.GetActorFromDB(e.Id)
- if err != nil {
- return err
- }
-
- if err := ArchivePosts(actor); err != nil {
- return err
- }
+ query := `select id from replies where id in (select inreplyto from replies where id=$1) and inreplyto=''`
+ if err := config.DB.QueryRow(query, link).Scan(&id); err != nil {
+ return "", nil
}
- return nil
+ return id, nil
}
func CheckInactive() {
@@ -496,54 +341,59 @@ func CheckInactive() {
}
func CheckInactiveInstances() (map[string]string, error) {
+ var rows *sql.Rows
+ var err error
+
instances := make(map[string]string)
- query := `select following from following`
- rows, err := config.DB.Query(query)
- if err != nil {
- return instances, err
+ query := `select following from following`
+ if rows, err = config.DB.Query(query); err != nil {
+ return instances, util.MakeError(err, "CheckInactiveInstances")
}
- defer rows.Close()
+ defer rows.Close()
for rows.Next() {
var instance string
+
if err := rows.Scan(&instance); err != nil {
- return instances, err
+ return instances, util.MakeError(err, "CheckInactiveInstances")
}
instances[instance] = instance
}
query = `select follower from follower`
- rows, err = config.DB.Query(query)
- if err != nil {
- return instances, err
+ if rows, err = config.DB.Query(query); err != nil {
+ return instances, util.MakeError(err, "CheckInactiveInstances")
}
- defer rows.Close()
+ defer rows.Close()
for rows.Next() {
var instance string
+
if err := rows.Scan(&instance); err != nil {
- return instances, err
+ return instances, util.MakeError(err, "CheckInactiveInstances")
}
instances[instance] = instance
}
re := regexp.MustCompile(config.Domain + `(.+)?`)
+
for _, e := range instances {
- actor, err := webfinger.GetActor(e)
+ actor, err := activitypub.GetActor(e)
+
if err != nil {
- return instances, err
+ return instances, util.MakeError(err, "CheckInactiveInstances")
}
if actor.Id == "" && !re.MatchString(e) {
- if err := AddInstanceToInactiveDB(e); err != nil {
- return instances, err
+ if err := AddInstanceToInactive(e); err != nil {
+ return instances, util.MakeError(err, "CheckInactiveInstances")
}
} else {
- if err := DeleteInstanceFromInactiveDB(e); err != nil {
- return instances, err
+ if err := DeleteInstanceFromInactive(e); err != nil {
+ return instances, util.MakeError(err, "CheckInactiveInstances")
}
}
}
@@ -552,12 +402,12 @@ func CheckInactiveInstances() (map[string]string, error) {
}
func GetAdminAuth() (string, string, error) {
- query := fmt.Sprintf("select identifier, code from boardaccess where board='%s' and type='admin'", config.Domain)
-
var code string
var identifier string
- if err := config.DB.QueryRow(query).Scan(&identifier, &code); err != nil {
- return "", "", err
+
+ query := `select identifier, code from boardaccess where board=$1 and type='admin'`
+ if err := config.DB.QueryRow(query, config.Domain).Scan(&identifier, &code); err != nil {
+ return "", "", nil
}
return code, identifier, nil
@@ -567,175 +417,27 @@ func IsHashBanned(hash string) (bool, error) {
var h string
query := `select hash from bannedmedia where hash=$1`
-
_ = config.DB.QueryRow(query, hash).Scan(&h)
return h == hash, nil
}
-func MakeCaptchas(total int) error {
- dbtotal, err := GetCaptchaTotal()
- if err != nil {
- return err
- }
-
- difference := total - dbtotal
-
- for i := 0; i < difference; i++ {
- if err := CreateNewCaptcha(); err != nil {
- return err
- }
- }
-
- return nil
-}
-
-func GetActorReported(w http.ResponseWriter, r *http.Request, id string) error {
- auth := r.Header.Get("Authorization")
- verification := strings.Split(auth, " ")
-
- if len(verification) < 2 {
- w.WriteHeader(http.StatusBadRequest)
- _, err := w.Write([]byte(""))
- return err
- }
-
- if res, err := HasAuth(verification[1], id); err == nil && !res {
- w.WriteHeader(http.StatusBadRequest)
- _, err = w.Write([]byte(""))
- return err
- } else if err != nil {
- return err
- }
-
- actor, _ := activitypub.GetActorFromDB(id)
-
- var following activitypub.Collection
- var err error
-
- following.AtContext.Context = "https://www.w3.org/ns/activitystreams"
- following.Type = "Collection"
- following.TotalItems, err = actor.GetReportedTotal()
- if err != nil {
- return err
- }
-
- following.Items, err = actor.GetReported()
- if err != nil {
- return err
- }
-
- enc, err := json.MarshalIndent(following, "", "\t")
- if err != nil {
- return err
- }
-
- w.Header().Set("Content-Type", config.ActivityStreams)
-
- _, err = w.Write(enc)
- return err
-}
-
func PrintAdminAuth() error {
- identifier, code, err := GetAdminAuth()
- if err != nil {
- return err
- }
-
- fmt.Println("Mod key: " + config.Key)
- fmt.Println("Admin Login: " + identifier + ", Code: " + code)
- return nil
-}
-
-func DeleteObjectRequest(id string) error {
- var nObj activitypub.ObjectBase
- var nActor activitypub.Actor
- nObj.Id = id
- nObj.Actor = nActor.Id
-
- activity, err := webfinger.CreateActivity("Delete", nObj)
- if err != nil {
- return err
- }
-
- obj, err := nObj.GetFromPath()
- if err != nil {
- return err
- }
+ code, identifier, err := GetAdminAuth()
- actor, err := webfinger.FingerActor(obj.Actor)
if err != nil {
- return err
- }
- activity.Actor = &actor
- objActor, _ := webfinger.GetActor(obj.Actor)
- followers, err := objActor.GetFollow()
- if err != nil {
- return err
- }
-
- for _, e := range followers {
- activity.To = append(activity.To, e.Id)
- }
-
- following, err := objActor.GetFollowing()
- if err != nil {
- return err
- }
- for _, e := range following {
- activity.To = append(activity.To, e.Id)
+ return util.MakeError(err, "PrintAdminAuth")
}
- return MakeActivityRequest(activity)
-}
-
-func DeleteObjectAndRepliesRequest(id string) error {
- var nObj activitypub.ObjectBase
- var nActor activitypub.Actor
- nObj.Id = id
- nObj.Actor = nActor.Id
-
- activity, err := webfinger.CreateActivity("Delete", nObj)
- if err != nil {
- return err
- }
-
- obj, err := nObj.GetCollectionFromPath()
- if err != nil {
- return err
- }
-
- activity.Actor.Id = obj.OrderedItems[0].Actor
-
- activity.Object = &obj.OrderedItems[0]
-
- objActor, _ := webfinger.GetActor(obj.OrderedItems[0].Actor)
- followers, err := objActor.GetFollow()
- if err != nil {
- return err
- }
- for _, e := range followers {
- activity.To = append(activity.To, e.Id)
- }
-
- following, err := objActor.GetFollowing()
- if err != nil {
- return err
- }
-
- for _, e := range following {
- activity.To = append(activity.To, e.Id)
- }
-
- return MakeActivityRequest(activity)
+ config.Log.Println("Mod key: " + config.Key)
+ config.Log.Println("Admin Login: " + identifier + ", Code: " + code)
+ return nil
}
-// root actor is used to follow remote feeds that are not local
-//name, prefname, summary, auth requirements, restricted
-func InitInstance() {
+func InitInstance() error {
if config.InstanceName != "" {
- if _, err := CreateNewBoardDB(*activitypub.CreateNewActor("", config.InstanceName, config.InstanceSummary, config.AuthReq, false)); err != nil {
- //panic(err)
+ if _, err := CreateNewBoard(*activitypub.CreateNewActor("", config.InstanceName, config.InstanceSummary, config.AuthReq, false)); err != nil {
+ return util.MakeError(err, "InitInstance")
}
if config.PublicIndexing == "true" {
@@ -743,4 +445,6 @@ func InitInstance() {
//AddInstanceToIndex(config.Domain)
}
}
+
+ return nil
}