Finished Prototype
This commit is contained in:
parent
ea54a27796
commit
6de476260d
30 changed files with 2189 additions and 0 deletions
117
utils/database/databaseConnector.go
Normal file
117
utils/database/databaseConnector.go
Normal file
|
@ -0,0 +1,117 @@
|
|||
package database
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
var DB *sql.DB
|
||||
|
||||
// TODO: Change DB Structure
|
||||
func InitDB(filepath string) (err error) {
|
||||
DB, err = sql.Open("sqlite3", filepath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if DB == nil {
|
||||
panic("DB couldn't be initialized")
|
||||
}
|
||||
|
||||
handleError(initObjectTable())
|
||||
handleError(initCollectionTable())
|
||||
handleError(initActorTable())
|
||||
handleError(initUserTable())
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func initObjectTable() (err error) {
|
||||
statement, err := DB.Prepare(`CREATE TABLE IF NOT EXISTS object (
|
||||
id TEXT PRIMARY KEY,
|
||||
type TEXT,
|
||||
attributedTo TEXT,
|
||||
content TEXT,
|
||||
published INTEGER,
|
||||
toActor TEXT
|
||||
)`)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
statement.Exec()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func initCollectionTable() (err error) {
|
||||
statement, err := DB.Prepare(`CREATE TABLE IF NOT EXISTS collection (
|
||||
id TEXT PRIMARY KEY
|
||||
)`)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
statement.Exec()
|
||||
|
||||
statement, err = DB.Prepare(`CREATE TABLE IF NOT EXISTS collectionObject (
|
||||
collectionId TEXT,
|
||||
objectId TEXT,
|
||||
PRIMARY KEY (collectionId, objectId)
|
||||
)`)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
statement.Exec()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func initActorTable() (err error) {
|
||||
statement, err := DB.Prepare(`CREATE TABLE IF NOT EXISTS actor (
|
||||
id TEXT PRIMARY KEY,
|
||||
type TEXT,
|
||||
name TEXT,
|
||||
preferredUsername TEXT,
|
||||
summary TEXT,
|
||||
inbox TEXT,
|
||||
outbox TEXT,
|
||||
followers TEXT,
|
||||
following TEXT,
|
||||
liked TEXT
|
||||
)`)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
statement.Exec()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func initUserTable() (err error) {
|
||||
statement, err := DB.Prepare(`CREATE TABLE IF NOT EXISTS user (
|
||||
id TEXT PRIMARY KEY,
|
||||
password TEXT,
|
||||
actor TEXT
|
||||
)`)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
statement.Exec()
|
||||
|
||||
statement, err = DB.Prepare(`CREATE TABLE IF NOT EXISTS session (
|
||||
token TEXT PRIMARY KEY,
|
||||
userId TEXT
|
||||
)`)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
statement.Exec()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func handleError(err error) {
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Could not execute Database Query: %s", err))
|
||||
}
|
||||
}
|
76
utils/encryptionService.go
Normal file
76
utils/encryptionService.go
Normal file
|
@ -0,0 +1,76 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"git.nutfactory.org/hoernschen/ActivityPub/config"
|
||||
)
|
||||
|
||||
func CreateToken() (err error, token string) {
|
||||
b := make([]byte, 8)
|
||||
_, err = rand.Read(b)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return
|
||||
}
|
||||
token = fmt.Sprintf("%x", b)
|
||||
return
|
||||
}
|
||||
|
||||
func CreateUUID() (err error, uuid string) {
|
||||
b := make([]byte, 16)
|
||||
_, err = rand.Read(b)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return
|
||||
}
|
||||
uuid = fmt.Sprintf("%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: Check if needed
|
||||
func Hash(s []byte) (err error, hashString string) {
|
||||
h := sha256.New()
|
||||
_, err = h.Write(s)
|
||||
if nil != err {
|
||||
return
|
||||
}
|
||||
hash := h.Sum(nil)
|
||||
hashString = base64.StdEncoding.EncodeToString(hash)
|
||||
return
|
||||
}
|
||||
|
||||
//TODO: Signing Mechanism?
|
||||
func GenerateKeyPair() (publicKey ed25519.PublicKey, privateKey ed25519.PrivateKey, err error) {
|
||||
publicKey, privateKey, err = ed25519.GenerateKey(nil)
|
||||
return
|
||||
}
|
||||
|
||||
func Sign(message []byte) string {
|
||||
signatureBytes := ed25519.Sign(config.PrivateKey, message)
|
||||
return base64.RawStdEncoding.EncodeToString(signatureBytes)
|
||||
}
|
||||
|
||||
func SignContent(content []byte) (signatures map[string]map[string]string) {
|
||||
if !config.Signing {
|
||||
return
|
||||
}
|
||||
signatures = make(map[string]map[string]string)
|
||||
signatures[config.Homeserver] = make(map[string]string)
|
||||
signatures[config.Homeserver][config.KeyId] = Sign(content)
|
||||
return
|
||||
}
|
||||
|
||||
func VerifySignature(publicKey []byte, message []byte, signature string) bool {
|
||||
signatureBytes, err := base64.RawStdEncoding.DecodeString(signature)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
ed25519.Verify(config.PublicKey, message, signatureBytes)
|
||||
return true
|
||||
}
|
23
utils/logger.go
Normal file
23
utils/logger.go
Normal file
|
@ -0,0 +1,23 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
func APILogger(inner http.Handler, name string) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
start := time.Now()
|
||||
|
||||
inner.ServeHTTP(w, r)
|
||||
|
||||
log.Printf(
|
||||
"%s\t%s\t%s\t%s",
|
||||
r.Method,
|
||||
r.RequestURI,
|
||||
name,
|
||||
time.Since(start),
|
||||
)
|
||||
})
|
||||
}
|
89
utils/requestChecker.go
Normal file
89
utils/requestChecker.go
Normal file
|
@ -0,0 +1,89 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"git.nutfactory.org/hoernschen/ActivityPub/config"
|
||||
)
|
||||
|
||||
type ErrorResponse struct {
|
||||
ErrorCode string `json:"errcode,omitempty"`
|
||||
ErrorMessage string `json:"error,omitempty"`
|
||||
RetryTime int `json:"retry_after_ms,omitempty"`
|
||||
}
|
||||
|
||||
func CheckRequest(r *http.Request) (err error) {
|
||||
if !strings.Contains(r.Header.Get("Content-Type"), "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"") {
|
||||
err = errors.New("Content Type not JSON")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GetContentTypeString() string {
|
||||
return "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""
|
||||
}
|
||||
|
||||
func GetDefaultContext() string {
|
||||
return "https://www.w3.org/ns/activitystreams"
|
||||
}
|
||||
|
||||
func GenerateProfileUrl(userId string) string {
|
||||
return fmt.Sprintf("%s://%s/%s/", config.HttpString, config.Homeserver, userId)
|
||||
}
|
||||
|
||||
func GenerateInboxUrl(userId string) string {
|
||||
return fmt.Sprintf("%s://%s/%s/inbox/", config.HttpString, config.Homeserver, userId)
|
||||
}
|
||||
|
||||
func GenerateOutboxUrl(userId string) string {
|
||||
return fmt.Sprintf("%s://%s/%s/outbox/", config.HttpString, config.Homeserver, userId)
|
||||
}
|
||||
|
||||
func GenerateFollowersUrl(userId string) string {
|
||||
return fmt.Sprintf("%s://%s/%s/followers/", config.HttpString, config.Homeserver, userId)
|
||||
}
|
||||
|
||||
func GenerateFollowingUrl(userId string) string {
|
||||
return fmt.Sprintf("%s://%s/%s/following/", config.HttpString, config.Homeserver, userId)
|
||||
}
|
||||
|
||||
func GenerateLikedUrl(userId string) string {
|
||||
return fmt.Sprintf("%s://%s/%s/liked/", config.HttpString, config.Homeserver, userId)
|
||||
}
|
||||
|
||||
func GetAccessToken(r *http.Request) (token string, err error) {
|
||||
token = r.URL.Query().Get("access_token")
|
||||
if token == "" {
|
||||
token = r.Header.Get("Authorization")
|
||||
if token == "" || !strings.Contains(token, "Bearer") {
|
||||
err = errors.New("Missing Token")
|
||||
} else {
|
||||
token = strings.Split(token, " ")[1]
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func HandleHTTPError(res *http.Response) (err error) {
|
||||
buf := new(bytes.Buffer)
|
||||
buf.ReadFrom(res.Body)
|
||||
err = errors.New(fmt.Sprintf("%s (%s)", buf.String(), res.Status))
|
||||
return
|
||||
}
|
||||
|
||||
func RemoveDuplicates(array []string) []string {
|
||||
keys := make(map[string]bool)
|
||||
list := []string{}
|
||||
|
||||
for _, entry := range array {
|
||||
if _, value := keys[entry]; !value {
|
||||
keys[entry] = true
|
||||
list = append(list, entry)
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
12
utils/router/route.go
Normal file
12
utils/router/route.go
Normal file
|
@ -0,0 +1,12 @@
|
|||
package router
|
||||
|
||||
import "net/http"
|
||||
|
||||
type Route struct {
|
||||
Name string
|
||||
Method string
|
||||
Pattern string
|
||||
HandlerFunc http.HandlerFunc
|
||||
}
|
||||
|
||||
type Routes []Route
|
27
utils/router/router.go
Normal file
27
utils/router/router.go
Normal file
|
@ -0,0 +1,27 @@
|
|||
package router
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"git.nutfactory.org/hoernschen/ActivityPub/utils"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
func NewRouter(routes Routes) *mux.Router {
|
||||
router := mux.NewRouter().StrictSlash(true)
|
||||
|
||||
for _, route := range routes {
|
||||
var handler http.Handler
|
||||
handler = route.HandlerFunc
|
||||
handler = utils.APILogger(handler, route.Name)
|
||||
|
||||
router.
|
||||
Methods(route.Method).
|
||||
Path(route.Pattern).
|
||||
Name(route.Name).
|
||||
Handler(handler)
|
||||
|
||||
}
|
||||
|
||||
return router
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue