init commit from when still exploring using Neo4J for DB
This commit is contained in:
@@ -0,0 +1,279 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
// "fmt"
|
||||
//"io"
|
||||
"log"
|
||||
"net/http"
|
||||
// "os"
|
||||
// "os/signal"
|
||||
"strconv"
|
||||
//"strings"
|
||||
// "sync"
|
||||
// "time"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
||||
)
|
||||
|
||||
// TODO: Need to test.
|
||||
func create_new_space(driver neo4j.DriverWithContext, driver_ctx context.Context) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
|
||||
// Must be a user to create a space.
|
||||
user_id, ok := user_id_from_context(r.Context())
|
||||
if !ok {
|
||||
log.Println("Invalid user ID")
|
||||
http.Error(w, "Invalid user ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
err := r.ParseMultipartForm(10 << 20) // Limit to 10MB
|
||||
if err != nil {
|
||||
log.Println("Unable to parse form:", err)
|
||||
http.Error(w, "Unable to parse form", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
var space map[string]any
|
||||
err = json.NewDecoder(r.Body).Decode(&space)
|
||||
|
||||
if space["id"] != -1 {
|
||||
log.Println("Attempt to create a space with a defined ID")
|
||||
http.Error(w, "Space ID cannot be provided.", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
stmt := `
|
||||
MATCH (owner:User)
|
||||
WHERE id(owner) = $user_id
|
||||
|
||||
CREATE (s:Space {
|
||||
created_at: datetime(),
|
||||
name: $name,
|
||||
description: $description
|
||||
})
|
||||
|
||||
CREATE (owner)-[:SPACE_MEMBER {role: "Owner"}]->(s)
|
||||
|
||||
UNWIND $members as member
|
||||
MATCH (m:User)
|
||||
WHERE id(m) = member.id
|
||||
CREATE (m)-[:SPACE_MEMBER {role: member.role}]->(s)
|
||||
|
||||
RETURN id(s) AS id,
|
||||
s.name AS name
|
||||
`
|
||||
|
||||
stmt_args := map[string]any{
|
||||
"user_id": user_id,
|
||||
"name": space["name"],
|
||||
"description": space["description"],
|
||||
"members": space["members"],
|
||||
}
|
||||
|
||||
result, err := neo4j.ExecuteQuery(driver_ctx, driver, stmt, stmt_args, neo4j.EagerResultTransformer, neo4j.ExecuteQueryWithDatabase("neo4j"))
|
||||
|
||||
if err != nil || len(result.Records) != 2 {
|
||||
log.Println("Error creating Space:", err)
|
||||
http.Error(w, "Failed to create Space", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
record := result.Records[0]
|
||||
space_id, _ := record.Get("id")
|
||||
space_name, _ := record.Get("name")
|
||||
|
||||
record_obj := map[string]any{
|
||||
"space_id": space_id,
|
||||
"space_name": space_name,
|
||||
}
|
||||
|
||||
obj, err := json.Marshal(record_obj)
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to marshal JSON.", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
w.Write(obj)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Need to implement for ADMIN ONLY
|
||||
func retrieve_all_spaces(driver neo4j.DriverWithContext, driver_ctx context.Context) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func retrieve_space(driver neo4j.DriverWithContext, driver_ctx context.Context) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Implement access for Public and Open Spaces
|
||||
func auth_user_in_space(driver neo4j.DriverWithContext, driver_ctx context.Context, user_id int, space_id int) bool {
|
||||
stmt := `
|
||||
MATCH (u:User), (s:Space)
|
||||
WHERE id(u) = $user_id AND id(s) = $space_id
|
||||
RETURN EXISTS((u)-[:SPACE_MEMBER]->(s))
|
||||
`
|
||||
|
||||
stmt_args := map[string]any{
|
||||
"user_id": user_id,
|
||||
"space_id": space_id,
|
||||
}
|
||||
|
||||
result, err := neo4j.ExecuteQuery(driver_ctx, driver, stmt, stmt_args, neo4j.EagerResultTransformer, neo4j.ExecuteQueryWithDatabase("neo4j"))
|
||||
if err != nil {
|
||||
log.Println("Something went wrong authorizing the user to a space.")
|
||||
return false
|
||||
}
|
||||
|
||||
if len(result.Records) > 0 {
|
||||
return result.Records[0].Values[0].(bool)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Implement
|
||||
func update_space(driver neo4j.DriverWithContext, driver_ctx context.Context) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Implement
|
||||
func delete_space(driver neo4j.DriverWithContext, driver_ctx context.Context) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Need to handle multiple topics.
|
||||
func retrieve_spaces_posts(driver neo4j.DriverWithContext, driver_ctx context.Context) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
|
||||
// Must be a user to create a space.
|
||||
user_id, ok := user_id_from_context(r.Context())
|
||||
if !ok {
|
||||
log.Println("Invalid user ID")
|
||||
http.Error(w, "Invalid user ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
space_id, _ := strconv.Atoi(mux.Vars(r)["space_id"])
|
||||
|
||||
if !auth_user_in_space(driver, driver_ctx, user_id, space_id) {
|
||||
log.Println("User", user_id, "attempted access to space", space_id, ", which is not allowed.")
|
||||
http.Error(w, "You are not a member of that space.", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
stmt := `
|
||||
MATCH (p:Post)-[:IN_SPACE]->(s:Space)
|
||||
MATCH (s)-[:SPACE_TYPE]->(st:SpaceType)
|
||||
MATCH (p)-[:POST_TYPE]->(pt:PostType)
|
||||
MATCH (p)-[:STATUS]->(ps:PostStatus)
|
||||
MATCH (p)-[:TAGGED_WITH]->(t:Topic)
|
||||
MATCH (a:User)-[:CREATED]->(p)
|
||||
|
||||
WHERE
|
||||
id(s) = $space_id AND
|
||||
ps.name = "Published"
|
||||
|
||||
RETURN
|
||||
id(a) AS author_id,
|
||||
a.username AS author_username,
|
||||
a.profile_picture AS author_picture,
|
||||
|
||||
p.title AS title,
|
||||
p.excerpt AS excerpt,
|
||||
p.location AS location,
|
||||
p.content AS content,
|
||||
|
||||
pt.name AS post_type,
|
||||
id(t) AS topic_id,
|
||||
t.name AS topic_name,
|
||||
|
||||
s.name AS space_name
|
||||
`
|
||||
|
||||
stmt_args := map[string]any{
|
||||
"space_id": space_id,
|
||||
}
|
||||
|
||||
result, err := neo4j.ExecuteQuery(driver_ctx, driver, stmt, stmt_args, neo4j.EagerResultTransformer, neo4j.ExecuteQueryWithDatabase("neo4j"))
|
||||
|
||||
if err != nil {
|
||||
log.Println("Something went wrong retrieving Posts for a Space. Error:", err)
|
||||
http.Error(w, "Error retrieving Posts from Space.", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
//
|
||||
// if !(len(result.Records) >= 2) {
|
||||
// log.Println("Failed to retrieve Posts for Space", space_id, "\n Error:", err)
|
||||
// http.Error(w, "Error retrieving Posts from Space.", http.StatusInternalServerError)
|
||||
// return
|
||||
// }
|
||||
|
||||
posts_obj := map[int]any{}
|
||||
for index, record := range result.Records {
|
||||
|
||||
author_id, _ := record.Get("author_id")
|
||||
author_username, _ := record.Get("author_username")
|
||||
author_picture, _ := record.Get("author_picture")
|
||||
|
||||
title, _ := record.Get("title")
|
||||
excerpt, _ := record.Get("excerpt")
|
||||
location, _ := record.Get("location")
|
||||
content, _ := record.Get("content")
|
||||
|
||||
post_type, _ := record.Get("post_type")
|
||||
topic_id, _ := record.Get("topic_id")
|
||||
topic_name, _ := record.Get("topic_name")
|
||||
space_name, _ := record.Get("space_name")
|
||||
|
||||
record_obj := map[string]any{
|
||||
"author_id": author_id,
|
||||
"author_username": author_username,
|
||||
"author_picture": author_picture,
|
||||
"title": title,
|
||||
"excerpt": excerpt,
|
||||
"location": location,
|
||||
"content": content,
|
||||
"post_type": post_type,
|
||||
"topic_id": topic_id,
|
||||
"topic_name": topic_name,
|
||||
"space_name": space_name,
|
||||
}
|
||||
|
||||
posts_obj[index] = record_obj
|
||||
}
|
||||
|
||||
obj, err := json.Marshal(posts_obj)
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to parse into JSON", http.StatusInternalServerError)
|
||||
log.Println("error marshalling json")
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(obj)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Implement for Space Member role == Administrator OR role == Owner
|
||||
func retrieve_spaces_users(driver neo4j.DriverWithContext, driver_ctx context.Context) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user