You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
150 lines
4.1 KiB
150 lines
4.1 KiB
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"log"
|
|
"net/http"
|
|
|
|
"git.aiterp.net/rpdata/api/graphql/loader"
|
|
"git.aiterp.net/rpdata/api/graphql/resolver"
|
|
"git.aiterp.net/rpdata/api/graphql/schema"
|
|
"git.aiterp.net/rpdata/api/internal/auth"
|
|
"git.aiterp.net/rpdata/api/internal/store"
|
|
"git.aiterp.net/rpdata/api/model/change"
|
|
"git.aiterp.net/rpdata/api/model/file"
|
|
logModel "git.aiterp.net/rpdata/api/model/log"
|
|
graphql "github.com/graph-gophers/graphql-go"
|
|
"github.com/graph-gophers/graphql-go/relay"
|
|
)
|
|
|
|
func main() {
|
|
err := store.Init()
|
|
if err != nil {
|
|
log.Fatalln("Failed to init store:", err)
|
|
}
|
|
|
|
n, err := logModel.UpdateAllCharacters()
|
|
if err != nil {
|
|
log.Println("Charcter updated stopped:", err)
|
|
}
|
|
log.Println("Updated characters on", n, "logs")
|
|
|
|
schema, err := graphql.ParseSchema(schema.String(), &resolver.Resolver{}, graphql.MaxParallelism(48))
|
|
if err != nil {
|
|
log.Fatalln("Failed to parse schema:", err)
|
|
}
|
|
|
|
http.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != "GET" {
|
|
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
|
|
w.Write(page)
|
|
}))
|
|
|
|
relayHandler := &relay.Handler{Schema: schema}
|
|
http.HandleFunc("/graphql", func(w http.ResponseWriter, r *http.Request) {
|
|
l := loader.New()
|
|
r = r.WithContext(l.ToContext(r.Context()))
|
|
|
|
r = auth.RequestWithToken(r)
|
|
|
|
relayHandler.ServeHTTP(w, r)
|
|
})
|
|
|
|
http.HandleFunc("/upload", func(w http.ResponseWriter, r *http.Request) {
|
|
r = auth.RequestWithToken(r)
|
|
|
|
token := auth.TokenFromContext(r.Context())
|
|
if !token.Permitted("file.upload") {
|
|
http.Error(w, "Unauthorized", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
if err := r.ParseMultipartForm(16384); err != nil {
|
|
http.Error(w, "Internal (1): "+err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
formFile, header, err := r.FormFile("file")
|
|
if err != nil || header == nil || formFile == nil {
|
|
http.Error(w, "No file provided", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
file, err := file.Upload(r.Context(), header.Filename, header.Header.Get("Content-Type"), token.UserID, header.Size, formFile)
|
|
if err != nil {
|
|
http.Error(w, "Internal (2): "+err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
json, err := json.Marshal(file)
|
|
if err != nil {
|
|
http.Error(w, "Internal (3): "+err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write(json)
|
|
})
|
|
|
|
change.InitializeTimeline()
|
|
go func() {
|
|
index := int64(0)
|
|
|
|
for {
|
|
index++
|
|
ch, err := change.Timeline.Get(context.Background(), index)
|
|
if err == change.ErrExpired {
|
|
continue
|
|
} else if err != nil {
|
|
log.Println("Timeline:", err)
|
|
break
|
|
}
|
|
|
|
log.Printf("Change: time=%s model=%s op=%s id=%s author=%s\n", ch.Time.Local().Format("[Mon Jan 02 15:04 MST]"), ch.Model, ch.Op, ch.ObjectID, ch.Author)
|
|
}
|
|
}()
|
|
|
|
log.Fatal(http.ListenAndServe(":17000", nil))
|
|
}
|
|
|
|
var page = []byte(`
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/graphiql/0.10.2/graphiql.css" />
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/fetch/1.1.0/fetch.min.js"></script>
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.5.4/react.min.js"></script>
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.5.4/react-dom.min.js"></script>
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/graphiql/0.10.2/graphiql.js"></script>
|
|
</head>
|
|
<body style="width: 100%; height: 100%; margin: 0; overflow: hidden;">
|
|
<div id="graphiql" style="height: 100vh;">Loading...</div>
|
|
<script>
|
|
function graphQLFetcher(graphQLParams) {
|
|
return fetch("/graphql", {
|
|
method: "post",
|
|
body: JSON.stringify(graphQLParams),
|
|
credentials: "include",
|
|
}).then(function (response) {
|
|
return response.text();
|
|
}).then(function (responseBody) {
|
|
try {
|
|
return JSON.parse(responseBody);
|
|
} catch (error) {
|
|
return responseBody;
|
|
}
|
|
});
|
|
}
|
|
ReactDOM.render(
|
|
React.createElement(GraphiQL, {fetcher: graphQLFetcher}),
|
|
document.getElementById("graphiql")
|
|
);
|
|
</script>
|
|
</body>
|
|
</html>
|
|
`)
|