diff --git a/apiGo/api/Actors.go b/apiGo/api/Actors.go index 1cc511f..df17514 100644 --- a/apiGo/api/Actors.go +++ b/apiGo/api/Actors.go @@ -2,6 +2,7 @@ package api import ( "fmt" + "openmediacenter/apiGo/api/api" "openmediacenter/apiGo/api/types" "openmediacenter/apiGo/database" ) @@ -23,9 +24,9 @@ func getActorsFromDB() { * @apiSuccess {string} .Name Actor Name * @apiSuccess {string} .Thumbnail Portrait Thumbnail */ - AddHandler("getAllActors", ActorNode, func(info *HandlerInfo) []byte { + api.AddHandler("getAllActors", api.ActorNode, api.PermUser, func(context api.Context) { query := "SELECT actor_id, name, thumbnail FROM actors" - return jsonify(readActorsFromResultset(database.Query(query))) + context.Json(readActorsFromResultset(database.Query(query))) }) /** @@ -41,20 +42,21 @@ func getActorsFromDB() { * @apiSuccess {string} .Name Actor Name * @apiSuccess {string} .Thumbnail Portrait Thumbnail */ - AddHandler("getActorsOfVideo", ActorNode, func(info *HandlerInfo) []byte { + api.AddHandler("getActorsOfVideo", api.ActorNode, api.PermUser, func(context api.Context) { var args struct { MovieId int } - if err := FillStruct(&args, info.Data); err != nil { - fmt.Println(err.Error()) - return nil + err := api.DecodeRequest(context.GetRequest(), &args) + if err != nil { + context.Text("failed to decode request") + return } query := fmt.Sprintf(`SELECT a.actor_id, name, thumbnail FROM actors_videos JOIN actors a on actors_videos.actor_id = a.actor_id WHERE actors_videos.video_id=%d`, args.MovieId) - return jsonify(readActorsFromResultset(database.Query(query))) + context.Json(readActorsFromResultset(database.Query(query))) }) /** @@ -74,13 +76,15 @@ func getActorsFromDB() { * @apiSuccess {string} Info.Name Actor Name * @apiSuccess {string} Info.Thumbnail Actor Thumbnail */ - AddHandler("getActorInfo", ActorNode, func(info *HandlerInfo) []byte { + api.AddHandler("getActorInfo", api.ActorNode, api.PermUser, func(context api.Context) { var args struct { ActorId int } - if err := FillStruct(&args, info.Data); err != nil { - fmt.Println(err.Error()) - return nil + + err := api.DecodeRequest(context.GetRequest(), &args) + if err != nil { + context.Error("unable to decode request") + return } query := fmt.Sprintf(`SELECT movie_id, movie_name FROM actors_videos @@ -99,7 +103,7 @@ func getActorsFromDB() { Info: actor, } - return jsonify(result) + context.Json(result) }) } @@ -112,19 +116,17 @@ func saveActorsToDB() { * * @apiParam {string} ActorName Name of new Actor * - * @apiSuccess {string} result 'success' if successfully or error message if not + * @apiSuccess {string} result 'success' if successfully or Error message if not */ - AddHandler("createActor", ActorNode, func(info *HandlerInfo) []byte { + api.AddHandler("createActor", api.ActorNode, api.PermUser, func(context api.Context) { var args struct { ActorName string } - if err := FillStruct(&args, info.Data); err != nil { - fmt.Println(err.Error()) - return nil - } + api.DecodeRequest(context.GetRequest(), &args) query := "INSERT IGNORE INTO actors (name) VALUES (?)" - return database.SuccessQuery(query, args.ActorName) + // todo bit ugly + context.Text(string(database.SuccessQuery(query, args.ActorName))) }) /** @@ -136,19 +138,20 @@ func saveActorsToDB() { * @apiParam {int} ActorId Id of Actor * @apiParam {int} MovieId Id of Movie to add to * - * @apiSuccess {string} result 'success' if successfully or error message if not + * @apiSuccess {string} result 'success' if successfully or Error message if not */ - AddHandler("addActorToVideo", ActorNode, func(info *HandlerInfo) []byte { + api.AddHandler("addActorToVideo", api.ActorNode, api.PermUser, func(context api.Context) { var args struct { ActorId int MovieId int } - if err := FillStruct(&args, info.Data); err != nil { - fmt.Println(err.Error()) - return nil + err := api.DecodeRequest(context.GetRequest(), &args) + if err != nil { + context.Error("unable to decode request") + return } query := fmt.Sprintf("INSERT IGNORE INTO actors_videos (actor_id, video_id) VALUES (%d,%d)", args.ActorId, args.MovieId) - return database.SuccessQuery(query) + context.Text(string(database.SuccessQuery(query))) }) } diff --git a/apiGo/api/ApiBase.go b/apiGo/api/ApiBase.go deleted file mode 100644 index 5120559..0000000 --- a/apiGo/api/ApiBase.go +++ /dev/null @@ -1,113 +0,0 @@ -package api - -import ( - "bytes" - "encoding/json" - "fmt" - "gopkg.in/oauth2.v3" - "net/http" - "openmediacenter/apiGo/api/oauth" -) - -const APIPREFIX = "/api" - -const ( - VideoNode = iota - TagNode = iota - SettingsNode = iota - ActorNode = iota - TVShowNode = iota -) - -type HandlerInfo struct { - ID string - Token string - Data map[string]interface{} -} - -type actionStruct struct { - Action string -} - -type Handler struct { - action string - handler func(info *HandlerInfo) []byte - apiNode int -} - -var handlers = make(map[string]Handler) - -func AddHandler(action string, apiNode int, h func(info *HandlerInfo) []byte) { - // append new handler to the handlers - handlers[fmt.Sprintf("%s/%d", action, apiNode)] = Handler{action, h, apiNode} -} - -func ServerInit() { - http.Handle(APIPREFIX+"/video", oauth.ValidateToken(handlefunc, VideoNode)) - http.Handle(APIPREFIX+"/tags", oauth.ValidateToken(handlefunc, TagNode)) - http.Handle(APIPREFIX+"/settings", oauth.ValidateToken(handlefunc, SettingsNode)) - http.Handle(APIPREFIX+"/actor", oauth.ValidateToken(handlefunc, ActorNode)) - http.Handle(APIPREFIX+"/tvshow", oauth.ValidateToken(handlefunc, TVShowNode)) - - // initialize oauth service and add corresponding auth routes - oauth.InitOAuth() -} - -func handleAPICall(action string, requestBody string, apiNode int, info *HandlerInfo) []byte { - handler, ok := handlers[fmt.Sprintf("%s/%d", action, apiNode)] - if !ok { - // handler doesn't exist! - fmt.Printf("no handler found for Action: %d/%s\n", apiNode, action) - return nil - } - - // check if info even exists - if info == nil { - info = &HandlerInfo{} - } - - // parse the arguments - var args map[string]interface{} - err := json.Unmarshal([]byte(requestBody), &args) - - if err != nil { - fmt.Printf("failed to decode arguments of action %s :: %s\n", action, requestBody) - } else { - // check if map has an action - if _, ok := args["action"]; ok { - delete(args, "action") - } - - info.Data = args - } - - // call the handler - return handler.handler(info) -} - -func handlefunc(rw http.ResponseWriter, req *http.Request, node int, tokenInfo *oauth2.TokenInfo) { - // only allow post requests - if req.Method != "POST" { - return - } - - buf := new(bytes.Buffer) - buf.ReadFrom(req.Body) - body := buf.String() - - var t actionStruct - err := json.Unmarshal([]byte(body), &t) - if err != nil { - fmt.Println("failed to read action from request! :: " + body) - } - - // load userid from received token object - id := (*tokenInfo).GetClientID() - - userinfo := &HandlerInfo{ - ID: id, - Token: (*tokenInfo).GetCode(), - } - - rw.Write(handleAPICall(t.Action, body, node, userinfo)) -} diff --git a/apiGo/api/Helpers.go b/apiGo/api/Helpers.go index 1696c57..282710c 100644 --- a/apiGo/api/Helpers.go +++ b/apiGo/api/Helpers.go @@ -2,10 +2,8 @@ package api import ( "database/sql" - "encoding/json" "fmt" "openmediacenter/apiGo/api/types" - "reflect" ) // MovieId - MovieName : pay attention to the order! @@ -33,7 +31,7 @@ func readTagsFromResultset(rows *sql.Rows) []types.Tag { var tag types.Tag err := rows.Scan(&tag.TagId, &tag.TagName) if err != nil { - panic(err.Error()) // proper error handling instead of panic in your app + panic(err.Error()) // proper Error handling instead of panic in your app } result = append(result, tag) } @@ -54,7 +52,7 @@ func readActorsFromResultset(rows *sql.Rows) []types.Actor { actor.Thumbnail = string(thumbnail) } if err != nil { - panic(err.Error()) // proper error handling instead of panic in your app + panic(err.Error()) // proper Error handling instead of panic in your app } result = append(result, actor) } @@ -70,7 +68,7 @@ func readTVshowsFromResultset(rows *sql.Rows) []types.TVShow { var vid types.TVShow err := rows.Scan(&vid.Id, &vid.Name) if err != nil { - panic(err.Error()) // proper error handling instead of panic in your app + panic(err.Error()) // proper Error handling instead of panic in your app } result = append(result, vid) } @@ -78,54 +76,3 @@ func readTVshowsFromResultset(rows *sql.Rows) []types.TVShow { return result } - -func jsonify(v interface{}) []byte { - // jsonify results - str, err := json.Marshal(v) - if err != nil { - fmt.Println("Error while Jsonifying return object: " + err.Error()) - } - return str -} - -// setField set a specific field of an object with an object provided -func setField(obj interface{}, name string, value interface{}) error { - structValue := reflect.ValueOf(obj).Elem() - structFieldValue := structValue.FieldByName(name) - - if !structFieldValue.IsValid() { - return fmt.Errorf("no such field: %s in obj", name) - } - - if !structFieldValue.CanSet() { - return fmt.Errorf("cannot set %s field value", name) - } - - structFieldType := structFieldValue.Type() - val := reflect.ValueOf(value) - - if structFieldType != val.Type() { - if val.Type().ConvertibleTo(structFieldType) { - // if type is convertible - convert and set - structFieldValue.Set(val.Convert(structFieldType)) - } else { - return fmt.Errorf("provided value %s type didn't match obj field type and isn't convertible", name) - } - } else { - // set value if type is the same - structFieldValue.Set(val) - } - - return nil -} - -// FillStruct fill a custom struct with objects of a map -func FillStruct(i interface{}, m map[string]interface{}) error { - for k, v := range m { - err := setField(i, k, v) - if err != nil { - return err - } - } - return nil -} diff --git a/apiGo/api/Settings.go b/apiGo/api/Settings.go index c5dedde..1775ed0 100644 --- a/apiGo/api/Settings.go +++ b/apiGo/api/Settings.go @@ -1,8 +1,7 @@ package api import ( - "encoding/json" - "fmt" + "openmediacenter/apiGo/api/api" "openmediacenter/apiGo/api/types" "openmediacenter/apiGo/config" "openmediacenter/apiGo/database" @@ -38,7 +37,7 @@ func getSettingsFromDB() { * @apiSuccess {uint32} Sizes.DifferentTags number of different tags available * @apiSuccess {uint32} Sizes.TagsAdded number of different tags added to videos */ - AddHandler("loadGeneralSettings", SettingsNode, func(info *HandlerInfo) []byte { + api.AddHandler("loadGeneralSettings", api.SettingsNode, api.PermUser, func(context api.Context) { result, _, sizes := database.GetSettings() var ret = struct { @@ -48,7 +47,7 @@ func getSettingsFromDB() { Settings: &result, Sizes: &sizes, } - return jsonify(ret) + context.Json(ret) }) /** @@ -64,7 +63,7 @@ func getSettingsFromDB() { * @apiSuccess {bool} DarkMode Darkmode enabled? * @apiSuccess {bool} TVShowEnabled is are TVShows enabled */ - AddHandler("loadInitialData", SettingsNode, func(info *HandlerInfo) []byte { + api.AddHandler("loadInitialData", api.SettingsNode, api.PermUser, func(context api.Context) { sett := settings.LoadSettings() type InitialDataTypeResponse struct { @@ -93,8 +92,7 @@ func getSettingsFromDB() { FullDeleteEnabled: config.GetConfig().Features.FullyDeletableVideos, } - str, _ := json.Marshal(res) - return str + context.Json(res) }) } @@ -112,13 +110,14 @@ func saveSettingsToDB() { * @apiParam {bool} TMDBGrabbing TMDB grabbing support to grab tag info and thumbnails * @apiParam {bool} DarkMode Darkmode enabled? * - * @apiSuccess {string} result 'success' if successfully or error message if not + * @apiSuccess {string} result 'success' if successfully or Error message if not */ - AddHandler("saveGeneralSettings", SettingsNode, func(info *HandlerInfo) []byte { + api.AddHandler("saveGeneralSettings", api.SettingsNode, api.PermUser, func(context api.Context) { var args types.SettingsType - if err := FillStruct(&args, info.Data); err != nil { - fmt.Println(err.Error()) - return nil + err := api.DecodeRequest(context.GetRequest(), &args) + if err != nil { + context.Error("unable to decode arguments") + return } query := ` @@ -130,9 +129,10 @@ func saveSettingsToDB() { TMDB_grabbing=?, DarkMode=? WHERE 1` - return database.SuccessQuery(query, + // todo avoid conversion + context.Text(string(database.SuccessQuery(query, args.VideoPath, args.EpisodePath, args.Password, - args.MediacenterName, args.TMDBGrabbing, args.DarkMode) + args.MediacenterName, args.TMDBGrabbing, args.DarkMode))) }) } @@ -144,11 +144,11 @@ func reIndexHandling() { * @apiName startReindex * @apiGroup Settings * - * @apiSuccess {string} result 'success' if successfully or error message if not + * @apiSuccess {string} result 'success' if successfully or Error message if not */ - AddHandler("startReindex", SettingsNode, func(info *HandlerInfo) []byte { + api.AddHandler("startReindex", api.SettingsNode, api.PermUser, func(context api.Context) { videoparser.StartReindex() - return database.ManualSuccessResponse(nil) + context.Text(string(database.ManualSuccessResponse(nil))) }) /** @@ -157,11 +157,11 @@ func reIndexHandling() { * @apiName startTVShowReindex * @apiGroup Settings * - * @apiSuccess {string} result 'success' if successfully or error message if not + * @apiSuccess {string} result 'success' if successfully or Error message if not */ - AddHandler("startTVShowReindex", SettingsNode, func(info *HandlerInfo) []byte { + api.AddHandler("startTVShowReindex", api.SettingsNode, api.PermUser, func(context api.Context) { videoparser.StartTVShowReindex() - return database.ManualSuccessResponse(nil) + context.Text(string(database.ManualSuccessResponse(nil))) }) /** @@ -170,8 +170,7 @@ func reIndexHandling() { * @apiName cleanupGravity * @apiGroup Settings */ - AddHandler("cleanupGravity", SettingsNode, func(info *HandlerInfo) []byte { + api.AddHandler("cleanupGravity", api.SettingsNode, api.PermUser, func(context api.Context) { videoparser.StartCleanup() - return nil }) } diff --git a/apiGo/api/TVShows.go b/apiGo/api/TVShows.go index 7004c61..0650abc 100644 --- a/apiGo/api/TVShows.go +++ b/apiGo/api/TVShows.go @@ -2,6 +2,7 @@ package api import ( "fmt" + "openmediacenter/apiGo/api/api" "openmediacenter/apiGo/config" "openmediacenter/apiGo/database" ) @@ -22,10 +23,10 @@ func AddTvshowHandlers() { * @apiSuccess {uint32} .Id tvshow id * @apiSuccess {string} .Name tvshow name */ - AddHandler("getTVShows", TVShowNode, func(info *HandlerInfo) []byte { + api.AddHandler("getTVShows", api.TVShowNode, api.PermUser, func(context api.Context) { query := "SELECT id, name FROM tvshow" rows := database.Query(query) - return jsonify(readTVshowsFromResultset(rows)) + context.Json(readTVshowsFromResultset(rows)) }) /** @@ -42,13 +43,14 @@ func AddTvshowHandlers() { * @apiSuccess {uint8} .Season Season number * @apiSuccess {uint8} .Episode Episode number */ - AddHandler("getEpisodes", TVShowNode, func(info *HandlerInfo) []byte { + api.AddHandler("getEpisodes", api.TVShowNode, api.PermUser, func(context api.Context) { var args struct { ShowID uint32 } - if err := FillStruct(&args, info.Data); err != nil { - fmt.Println(err.Error()) - return nil + err := api.DecodeRequest(context.GetRequest(), &args) + if err != nil { + context.Text("unable to decode request") + return } query := fmt.Sprintf("SELECT id, name, season, episode FROM tvshow_episodes WHERE tvshow_id=%d", args.ShowID) @@ -73,7 +75,7 @@ func AddTvshowHandlers() { episodes = append(episodes, ep) } - return jsonify(episodes) + context.Json(episodes) }) /** @@ -90,13 +92,14 @@ func AddTvshowHandlers() { * @apiSuccess {uint8} Episode Episode number * @apiSuccess {string} Path webserver path of video file */ - AddHandler("loadEpisode", TVShowNode, func(info *HandlerInfo) []byte { + api.AddHandler("loadEpisode", api.TVShowNode, api.PermUser, func(context api.Context) { var args struct { ID uint32 } - if err := FillStruct(&args, info.Data); err != nil { - fmt.Println(err.Error()) - return nil + err := api.DecodeRequest(context.GetRequest(), &args) + if err != nil { + context.Text("unable to decode argument") + return } query := fmt.Sprintf(` @@ -116,15 +119,16 @@ WHERE tvshow_episodes.id=%d`, args.ID) var filename string var foldername string - err := row.Scan(&ret.Name, &ret.Season, &ret.TVShowID, &ret.Episode, &filename, &foldername) + err = row.Scan(&ret.Name, &ret.Season, &ret.TVShowID, &ret.Episode, &filename, &foldername) if err != nil { fmt.Println(err.Error()) - return nil + context.Error(err.Error()) + return } ret.Path = foldername + "/" + filename - return jsonify(ret) + context.Json(ret) }) /** @@ -137,25 +141,26 @@ WHERE tvshow_episodes.id=%d`, args.ID) * * @apiSuccess {string} . Base64 encoded Thubnail */ - AddHandler("readThumbnail", TVShowNode, func(info *HandlerInfo) []byte { + api.AddHandler("readThumbnail", api.TVShowNode, api.PermUser, func(context api.Context) { var args struct { Id int } - if err := FillStruct(&args, info.Data); err != nil { - fmt.Println(err.Error()) - return nil + err := api.DecodeRequest(context.GetRequest(), &args) + if err != nil { + context.Text("unable to decode request") + return } var pic []byte query := fmt.Sprintf("SELECT thumbnail FROM tvshow WHERE id=%d", args.Id) - err := database.QueryRow(query).Scan(&pic) + err = database.QueryRow(query).Scan(&pic) if err != nil { fmt.Printf("the thumbnail of movie id %d couldn't be found", args.Id) - return nil + return } - return pic + context.Text(string(pic)) }) } diff --git a/apiGo/api/Tags.go b/apiGo/api/Tags.go index 13a6a54..357ee25 100644 --- a/apiGo/api/Tags.go +++ b/apiGo/api/Tags.go @@ -2,6 +2,7 @@ package api import ( "fmt" + "openmediacenter/apiGo/api/api" "openmediacenter/apiGo/database" "regexp" ) @@ -22,16 +23,17 @@ func deleteFromDB() { * @apiParam {bool} [Force] force delete tag with its constraints * @apiParam {int} TagId id of tag to delete * - * @apiSuccess {string} result 'success' if successfully or error message if not + * @apiSuccess {string} result 'success' if successfully or Error message if not */ - AddHandler("deleteTag", TagNode, func(info *HandlerInfo) []byte { + api.AddHandler("deleteTag", api.TagNode, api.PermUser, func(context api.Context) { var args struct { TagId int Force bool } - if err := FillStruct(&args, info.Data); err != nil { - fmt.Println(err.Error()) - return nil + err := api.DecodeRequest(context.GetRequest(), &args) + if err != nil { + context.Text("unable to decode request") + return } // delete key constraints first @@ -41,23 +43,24 @@ func deleteFromDB() { // respond only if result not successful if err != nil { - return database.ManualSuccessResponse(err) + context.Text(string(database.ManualSuccessResponse(err))) + return } } query := fmt.Sprintf("DELETE FROM tags WHERE tag_id=%d", args.TagId) - err := database.Edit(query) + err = database.Edit(query) if err == nil { // return if successful - return database.ManualSuccessResponse(err) + context.Text(string(database.ManualSuccessResponse(err))) } else { - // check with regex if its the key constraint error + // check with regex if its the key constraint Error r := regexp.MustCompile("^.*a foreign key constraint fails.*$") if r.MatchString(err.Error()) { - return database.ManualSuccessResponse(fmt.Errorf("not empty tag")) + context.Text(string(database.ManualSuccessResponse(fmt.Errorf("not empty tag")))) } else { - return database.ManualSuccessResponse(err) + context.Text(string(database.ManualSuccessResponse(err))) } } }) @@ -74,9 +77,9 @@ func getFromDB() { * @apiSuccess {uint32} TagId * @apiSuccess {string} TagName name of the Tag */ - AddHandler("getAllTags", TagNode, func(info *HandlerInfo) []byte { + api.AddHandler("getAllTags", api.TagNode, api.PermUser, func(context api.Context) { query := "SELECT tag_id,tag_name from tags" - return jsonify(readTagsFromResultset(database.Query(query))) + context.Json(readTagsFromResultset(database.Query(query))) }) } @@ -89,19 +92,20 @@ func addToDB() { * * @apiParam {string} TagName name of the tag * - * @apiSuccess {string} result 'success' if successfully or error message if not + * @apiSuccess {string} result 'success' if successfully or Error message if not */ - AddHandler("createTag", TagNode, func(info *HandlerInfo) []byte { + api.AddHandler("createTag", api.TagNode, api.PermUser, func(context api.Context) { var args struct { TagName string } - if err := FillStruct(&args, info.Data); err != nil { - fmt.Println(err.Error()) - return nil + err := api.DecodeRequest(context.GetRequest(), &args) + if err != nil { + context.Text("unable to decode request") + return } query := "INSERT IGNORE INTO tags (tag_name) VALUES (?)" - return database.SuccessQuery(query, args.TagName) + context.Text(string(database.SuccessQuery(query, args.TagName))) }) /** @@ -113,19 +117,20 @@ func addToDB() { * @apiParam {int} TagId Tag id to add to video * @apiParam {int} MovieId Video Id of video to add tag to * - * @apiSuccess {string} result 'success' if successfully or error message if not + * @apiSuccess {string} result 'success' if successfully or Error message if not */ - AddHandler("addTag", TagNode, func(info *HandlerInfo) []byte { + api.AddHandler("addTag", api.TagNode, api.PermUser, func(context api.Context) { var args struct { MovieId int TagId int } - if err := FillStruct(&args, info.Data); err != nil { - fmt.Println(err.Error()) - return nil + err := api.DecodeRequest(context.GetRequest(), &args) + if err != nil { + context.Text("unable to decode request") + return } query := "INSERT IGNORE INTO video_tags(tag_id, video_id) VALUES (?,?)" - return database.SuccessQuery(query, args.TagId, args.MovieId) + context.Text(string(database.SuccessQuery(query, args.TagId, args.MovieId))) }) } diff --git a/apiGo/api/Video.go b/apiGo/api/Video.go index 4af0ba5..aa31057 100644 --- a/apiGo/api/Video.go +++ b/apiGo/api/Video.go @@ -1,9 +1,9 @@ package api import ( - "encoding/json" "fmt" "net/url" + "openmediacenter/apiGo/api/api" "openmediacenter/apiGo/api/types" "openmediacenter/apiGo/config" "openmediacenter/apiGo/database" @@ -31,14 +31,15 @@ func getVideoHandlers() { * @apiSuccess {String} Videos.MovieName Name of video * @apiSuccess {String} TagName Name of the Tag returned */ - AddHandler("getMovies", VideoNode, func(info *HandlerInfo) []byte { + api.AddHandler("getMovies", api.VideoNode, api.PermUser, func(context api.Context) { var args struct { Tag uint32 Sort uint8 } - if err := FillStruct(&args, info.Data); err != nil { - fmt.Println(err.Error()) - return nil + err := api.DecodeRequest(context.GetRequest(), &args) + if err != nil { + context.Text("unable to decode request") + return } const ( @@ -92,24 +93,22 @@ func getVideoHandlers() { var vid types.VideoUnloadedType err := rows.Scan(&vid.MovieId, &vid.MovieName, &name) if err != nil { - return nil + return } vids = append(vids, vid) } if rows.Close() != nil { - return nil + return } // if the tag id doesn't exist the query won't return a name if name == "" { - return nil + return } result.Videos = vids result.TagName = name - // jsonify results - str, _ := json.Marshal(result) - return str + context.Json(result) }) /** @@ -122,26 +121,27 @@ func getVideoHandlers() { * * @apiSuccess {string} . Base64 encoded Thubnail */ - AddHandler("readThumbnail", VideoNode, func(info *HandlerInfo) []byte { + api.AddHandler("readThumbnail", api.VideoNode, api.PermUser, func(context api.Context) { var args struct { Movieid int } - if err := FillStruct(&args, info.Data); err != nil { - fmt.Println(err.Error()) - return nil + err := api.DecodeRequest(context.GetRequest(), &args) + if err != nil { + context.Text("unable to decode request") + return } var pic []byte query := fmt.Sprintf("SELECT thumbnail FROM videos WHERE movie_id=%d", args.Movieid) - err := database.QueryRow(query).Scan(&pic) + err = database.QueryRow(query).Scan(&pic) if err != nil { fmt.Printf("the thumbnail of movie id %d couldn't be found", args.Movieid) - return nil + return } - return pic + context.Text(string(pic)) }) /** @@ -160,13 +160,13 @@ func getVideoHandlers() { * @apiSuccess {string} Videos.MovieName Video Name * @apiSuccess {int} Videos.MovieId Video ID */ - AddHandler("getRandomMovies", VideoNode, func(info *HandlerInfo) []byte { + api.AddHandler("getRandomMovies", api.VideoNode, api.PermUser, func(context api.Context) { var args struct { Number int } - if err := FillStruct(&args, info.Data); err != nil { - fmt.Println(err.Error()) - return nil + if api.DecodeRequest(context.GetRequest(), &args) != nil { + context.Text("unable to decode request") + return } var result struct { @@ -198,15 +198,13 @@ func getVideoHandlers() { var tag types.Tag err := rows.Scan(&tag.TagName, &tag.TagId) if err != nil { - panic(err.Error()) // proper error handling instead of panic in your app + panic(err.Error()) // proper Error handling instead of panic in your app } // append to final array result.Tags = append(result.Tags, tag) } - // jsonify results - str, _ := json.Marshal(result) - return str + context.Json(result) }) /** @@ -221,23 +219,19 @@ func getVideoHandlers() { * @apiSuccess {number} .MovieId Id of Video * @apiSuccess {String} .MovieName Name of video */ - AddHandler("getSearchKeyWord", VideoNode, func(info *HandlerInfo) []byte { + api.AddHandler("getSearchKeyWord", api.VideoNode, api.PermUser, func(context api.Context) { var args struct { KeyWord string } - if err := FillStruct(&args, info.Data); err != nil { - fmt.Println(err.Error()) - return nil + if api.DecodeRequest(context.GetRequest(), &args) != nil { + context.Text("unable to decode request") + return } query := fmt.Sprintf(`SELECT movie_id,movie_name FROM videos WHERE movie_name LIKE '%%%s%%' ORDER BY likes DESC, create_date DESC, movie_name`, args.KeyWord) - - result := readVideosFromResultset(database.Query(query)) - // jsonify results - str, _ := json.Marshal(result) - return str + context.Json(readVideosFromResultset(database.Query(query))) }) } @@ -273,13 +267,13 @@ func loadVideosHandlers() { * @apiSuccess {string} Actors.Name Actor Name * @apiSuccess {string} Actors.Thumbnail Portrait Thumbnail */ - AddHandler("loadVideo", VideoNode, func(info *HandlerInfo) []byte { + api.AddHandler("loadVideo", api.VideoNode, api.PermUser, func(context api.Context) { var args struct { MovieId int } - if err := FillStruct(&args, info.Data); err != nil { - fmt.Println(err.Error()) - return nil + if api.DecodeRequest(context.GetRequest(), &args) != nil { + context.Text("unable to decode request") + return } query := fmt.Sprintf(`SELECT movie_name,movie_url,movie_id,thumbnail,poster,likes,quality,length @@ -291,9 +285,9 @@ func loadVideosHandlers() { err := database.QueryRow(query).Scan(&res.MovieName, &res.MovieUrl, &res.MovieId, &thumbnail, &poster, &res.Likes, &res.Quality, &res.Length) if err != nil { - fmt.Printf("error getting full data list of videoid - %d", args.MovieId) + fmt.Printf("Error getting full data list of videoid - %d", args.MovieId) fmt.Println(err.Error()) - return nil + return } // we ned to urlencode the movieurl @@ -331,9 +325,7 @@ func loadVideosHandlers() { res.Actors = readActorsFromResultset(database.Query(query)) - // jsonify results - str, _ := json.Marshal(res) - return str + context.Json(res) }) /** @@ -349,7 +341,7 @@ func loadVideosHandlers() { * @apiSuccess {uint32} DifferentTags number of different Tags available * @apiSuccess {uint32} Tagged number of different Tags assigned */ - AddHandler("getStartData", VideoNode, func(info *HandlerInfo) []byte { + api.AddHandler("getStartData", api.VideoNode, api.PermUser, func(context api.Context) { var result types.StartData // query settings and infotile values query := ` @@ -383,9 +375,7 @@ func loadVideosHandlers() { _ = database.QueryRow(query).Scan(&result.VideoNr, &result.Tagged, &result.HDNr, &result.FullHdNr, &result.SDNr, &result.DifferentTags) - // jsonify results - str, _ := json.Marshal(result) - return str + context.Json(result) }) } @@ -398,19 +388,19 @@ func addToVideoHandlers() { * * @apiParam {int} MovieId ID of video * - * @apiSuccess {string} result 'success' if successfully or error message if not + * @apiSuccess {string} result 'success' if successfully or Error message if not */ - AddHandler("addLike", VideoNode, func(info *HandlerInfo) []byte { + api.AddHandler("addLike", api.VideoNode, api.PermUser, func(context api.Context) { var args struct { MovieId int } - if err := FillStruct(&args, info.Data); err != nil { - fmt.Println(err.Error()) - return nil + if api.DecodeRequest(context.GetRequest(), &args) != nil { + context.Text("unable to decode request") + return } query := fmt.Sprintf("update videos set likes = likes + 1 where movie_id = %d", args.MovieId) - return database.SuccessQuery(query) + context.Text(string(database.SuccessQuery(query))) }) /** @@ -422,16 +412,16 @@ func addToVideoHandlers() { * @apiParam {int} MovieId ID of video * @apiParam {bool} FullyDelete Delete video from disk? * - * @apiSuccess {string} result 'success' if successfully or error message if not + * @apiSuccess {string} result 'success' if successfully or Error message if not */ - AddHandler("deleteVideo", VideoNode, func(info *HandlerInfo) []byte { + api.AddHandler("deleteVideo", api.VideoNode, api.PermUser, func(context api.Context) { var args struct { MovieId int FullyDelete bool } - if err := FillStruct(&args, info.Data); err != nil { - fmt.Println(err.Error()) - return nil + if api.DecodeRequest(context.GetRequest(), &args) != nil { + context.Text("unable to decode request") + return } // delete tag constraints @@ -444,7 +434,7 @@ func addToVideoHandlers() { // respond only if result not successful if err != nil { - return database.ManualSuccessResponse(err) + context.Text(string(database.ManualSuccessResponse(err))) } // only allow deletion of video if cli flag is set, independent of passed api arg @@ -454,7 +444,7 @@ func addToVideoHandlers() { var vidpath string err := database.QueryRow(query).Scan(&vidpath) if err != nil { - return database.ManualSuccessResponse(err) + context.Text(string(database.ManualSuccessResponse(err))) } sett, videoprefix, _ := database.GetSettings() @@ -463,12 +453,12 @@ func addToVideoHandlers() { err = os.Remove(assembledPath) if err != nil { fmt.Printf("unable to delete file: %s -- %s\n", assembledPath, err.Error()) - return database.ManualSuccessResponse(err) + context.Text(string(database.ManualSuccessResponse(err))) } } // delete video row from db query = fmt.Sprintf("DELETE FROM videos WHERE movie_id=%d", args.MovieId) - return database.SuccessQuery(query) + context.Text(string(database.SuccessQuery(query))) }) } diff --git a/apiGo/api/api/ApiBase.go b/apiGo/api/api/ApiBase.go new file mode 100644 index 0000000..c33efc8 --- /dev/null +++ b/apiGo/api/api/ApiBase.go @@ -0,0 +1,125 @@ +package api + +import ( + "fmt" + "net/http" +) + +const ( + VideoNode = "video" + TagNode = "tag" + SettingsNode = "setting" + ActorNode = "actor" + TVShowNode = "tv" + LoginNode = "login" +) + +//type HandlerInfo struct { +// ID string +// Token string +// Data map[string]interface{} +//} + +//type actionStruct struct { +// Action string +//} + +//type Handler struct { +// action string +// handler api.PermUser, func(context api.Context) +// apiNode int +//} + +func AddHandler(action string, apiNode string, perm uint8, handler func(ctx Context)) { + http.Handle(fmt.Sprintf("/api/%s/%s", apiNode, action), http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { + tokenheader := request.Header.Get("Token") + + id := -1 + permid := PermUnauthorized + + // check token if token provided + if tokenheader != "" { + id, permid = TokenValid(request.Header.Get("Token")) + } + + ctx := &apicontext{writer: writer, responseWritten: false, request: request, userid: id, permid: permid} + + // check if rights are sufficient to perform the action + if permid <= perm { + handler(ctx) + + if !ctx.responseWritten { + // none of the response functions called so send default response + ctx.Error("Unknown server Error occured") + writer.WriteHeader(501) + } + } else { + ctx.Error("insufficient permissions") + writer.WriteHeader(501) + } + })) +} + +func ServerInit() { + // initialize auth service and add corresponding auth routes + InitOAuth() +} + +//func handleAPICall(action string, requestBody string, apiNode int, context api.Context) { +// handler, ok := handlers[fmt.Sprintf("%s/%d", action, apiNode)] +// if !ok { +// // handler doesn't exist! +// fmt.Printf("no handler found for Action: %d/%s\n", apiNode, action) +// return nil +// } +// +// // check if info even exists +// if info == nil { +// info = &HandlerInfo{} +// } +// +// // parse the arguments +// var args map[string]interface{} +// err := json.Unmarshal([]byte(requestBody), &args) +// +// if err != nil { +// fmt.Printf("failed to decode arguments of action %s :: %s\n", action, requestBody) +// } else { +// // check if map has an action +// if _, ok := args["action"]; ok { +// delete(args, "action") +// } +// +// info.Data = args +// } +// +// // call the handler +// return handler.handler(info) +//} +// +//func handlefunc(rw http.ResponseWriter, req *http.Request, node int, tokenInfo *oauth2.TokenInfo) { +// // only allow post requests +// if req.Method != "POST" { +// return +// } +// +// buf := new(bytes.Buffer) +// buf.ReadFrom(req.Body) +// body := buf.String() +// +// var t actionStruct +// err := json.Unmarshal([]byte(body), &t) +// if err != nil { +// fmt.Println("failed to read action from request! :: " + body) +// } +// +// // load userid from received token object +// id := (*tokenInfo).GetClientID() +// +// userinfo := &HandlerInfo{ +// ID: id, +// Token: (*tokenInfo).GetCode(), +// } +// +// rw.Write(handleAPICall(t.Action, body, node, userinfo)) +//} diff --git a/apiGo/api/ApiBase_test.go b/apiGo/api/api/ApiBase_test.go similarity index 84% rename from apiGo/api/ApiBase_test.go rename to apiGo/api/api/ApiBase_test.go index d692f01..1d86191 100644 --- a/apiGo/api/ApiBase_test.go +++ b/apiGo/api/api/ApiBase_test.go @@ -11,7 +11,7 @@ func cleanUp() { func TestAddHandler(t *testing.T) { cleanUp() - AddHandler("test", ActorNode, func(info *HandlerInfo) []byte { + AddHandler("test", ActorNode, api.PermUser, func(context api.Context) { return nil }) if len(handlers) != 1 { @@ -23,7 +23,7 @@ func TestCallOfHandler(t *testing.T) { cleanUp() i := 0 - AddHandler("test", ActorNode, func(info *HandlerInfo) []byte { + AddHandler("test", ActorNode, api.PermUser, func(context api.Context) { i++ return nil }) @@ -39,7 +39,7 @@ func TestCallOfHandler(t *testing.T) { func TestDecodingOfArguments(t *testing.T) { cleanUp() - AddHandler("test", ActorNode, func(info *HandlerInfo) []byte { + AddHandler("test", ActorNode, api.PermUser, func(context api.Context) { var args struct { Test string TestInt int diff --git a/apiGo/api/api/Auth.go b/apiGo/api/api/Auth.go new file mode 100644 index 0000000..85aa07f --- /dev/null +++ b/apiGo/api/api/Auth.go @@ -0,0 +1,119 @@ +package api + +import ( + "fmt" + "github.com/dgrijalva/jwt-go" + "gopkg.in/oauth2.v3" + "gopkg.in/oauth2.v3/server" + "net/http" + "openmediacenter/apiGo/database" + "strconv" + "time" +) + +var srv *server.Server + +const ( + PermAdmin uint8 = iota + PermUser uint8 = iota + PermUnauthorized uint8 = iota +) + +const SignKey = "89013f1753a6890c6090b09e3c23ff43" +const TokenExpireHours = 24 + +type Token struct { + Token string + ExpiresAt int64 +} + +func TokenValid(token string) (int, uint8) { + t, err := jwt.ParseWithClaims(token, &jwt.StandardClaims{}, func(token *jwt.Token) (interface{}, error) { + return []byte(SignKey), nil + }) + if err != nil { + return -1, PermUnauthorized + } + + claims := t.Claims.(*jwt.StandardClaims) + + id, err := strconv.Atoi(claims.Issuer) + permid, err := strconv.Atoi(claims.Subject) + if err != nil { + return -1, PermUnauthorized + } + return id, uint8(permid) +} + +func InitOAuth() { + AddHandler("login", LoginNode, PermUnauthorized, func(ctx Context) { + var t struct { + Username string + Password string + } + + if DecodeRequest(ctx.GetRequest(), &t) != nil { + fmt.Println("Error accured while decoding Testrequest!!") + } + + // empty check + if t.Password == "" || t.Username == "" { + ctx.Error("empty username or password") + return + } + + // generate Argon2 Hash of passed pwd + pwd := HashPassword(t.Password) + + var id uint + var name string + var rightid uint8 + + err := database.QueryRow("SELECT userId,userName,rightId FROM User WHERE userName=? AND password=?", t.Username, *pwd).Scan(&id, &name, &rightid) + if err != nil { + ctx.Error("unauthorized") + return + } + + expires := time.Now().Add(time.Hour * TokenExpireHours).Unix() + claims := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.StandardClaims{ + Issuer: strconv.Itoa(int(id)), + Subject: strconv.Itoa(int(rightid)), + ExpiresAt: expires, + }) + + token, err := claims.SignedString([]byte(SignKey)) + if err != nil { + fmt.Println(err.Error()) + ctx.Error("failed to generate authorization token") + return + } + + type ResponseType struct { + Token Token + Username string + UserPerm uint8 + } + + ctx.Json(ResponseType{ + Token: Token{ + Token: token, + ExpiresAt: expires, + }, + Username: t.Username, + UserPerm: rightid, + }) + }) +} + +func ValidateToken(f func(rw http.ResponseWriter, req *http.Request, node int, tokenInfo *oauth2.TokenInfo), node int) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + tokeninfo, err := srv.ValidationBearerToken(r) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + f(w, r, node, &tokeninfo) + } +} diff --git a/apiGo/api/api/Context.go b/apiGo/api/api/Context.go new file mode 100644 index 0000000..d2bfb2d --- /dev/null +++ b/apiGo/api/api/Context.go @@ -0,0 +1,60 @@ +package api + +import ( + "fmt" + "net/http" +) + +type Context interface { + Json(t interface{}) + Text(msg string) + Error(msg string) + Errorf(msg string, args ...interface{}) + GetRequest() *http.Request + GetWriter() http.ResponseWriter + UserID() int +} + +type apicontext struct { + writer http.ResponseWriter + request *http.Request + responseWritten bool + userid int + permid uint8 +} + +func (r *apicontext) GetRequest() *http.Request { + return r.request +} + +func (r *apicontext) UserID() int { + return r.userid +} + +func (r *apicontext) GetWriter() http.ResponseWriter { + return r.writer +} + +func (r *apicontext) Json(t interface{}) { + r.writer.Write(Jsonify(t)) + r.responseWritten = true +} + +func (r *apicontext) Text(msg string) { + r.writer.Write([]byte(msg)) + r.responseWritten = true +} + +func (r *apicontext) Error(msg string) { + type Error struct { + Message string + } + + r.writer.WriteHeader(500) + r.writer.Write(Jsonify(Error{Message: msg})) + r.responseWritten = true +} + +func (r *apicontext) Errorf(msg string, args ...interface{}) { + r.Error(fmt.Sprintf(msg, args)) +} diff --git a/apiGo/api/api/Hash.go b/apiGo/api/api/Hash.go new file mode 100644 index 0000000..7ddd8e5 --- /dev/null +++ b/apiGo/api/api/Hash.go @@ -0,0 +1,13 @@ +package api + +import ( + "encoding/hex" + "golang.org/x/crypto/argon2" +) + +func HashPassword(pwd string) *string { + // todo generate random salt + hash := argon2.IDKey([]byte(pwd), []byte(SignKey), 3, 64*1024, 2, 32) + hexx := hex.EncodeToString(hash) + return &hexx +} diff --git a/apiGo/api/api/Helpers.go b/apiGo/api/api/Helpers.go new file mode 100644 index 0000000..0b4f338 --- /dev/null +++ b/apiGo/api/api/Helpers.go @@ -0,0 +1,74 @@ +package api + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" + "reflect" +) + +func Jsonify(v interface{}) []byte { + // Jsonify results + str, err := json.Marshal(v) + if err != nil { + fmt.Println("Error while Jsonifying return object: " + err.Error()) + } + return str +} + +// DecodeRequest decodes the request +func DecodeRequest(request *http.Request, arg interface{}) error { + buf := new(bytes.Buffer) + buf.ReadFrom(request.Body) + body := buf.String() + + err := json.Unmarshal([]byte(body), &arg) + if err != nil { + fmt.Println("JSON decode Error" + err.Error()) + } + + return err +} + +// setField set a specific field of an object with an object provided +func setField(obj interface{}, name string, value interface{}) error { + structValue := reflect.ValueOf(obj).Elem() + structFieldValue := structValue.FieldByName(name) + + if !structFieldValue.IsValid() { + return fmt.Errorf("no such field: %s in obj", name) + } + + if !structFieldValue.CanSet() { + return fmt.Errorf("cannot set %s field value", name) + } + + structFieldType := structFieldValue.Type() + val := reflect.ValueOf(value) + + if structFieldType != val.Type() { + if val.Type().ConvertibleTo(structFieldType) { + // if type is convertible - convert and set + structFieldValue.Set(val.Convert(structFieldType)) + } else { + return fmt.Errorf("provided value %s type didn't match obj field type and isn't convertible", name) + } + } else { + // set value if type is the same + structFieldValue.Set(val) + } + + return nil +} + +// FillStruct fill a custom struct with objects of a map +func FillStruct(i interface{}, m map[string]interface{}) error { + for k, v := range m { + err := setField(i, k, v) + if err != nil { + return err + } + } + return nil +} diff --git a/apiGo/api/oauth/CustomClientStore.go b/apiGo/api/oauth/CustomClientStore.go deleted file mode 100644 index 414dfb6..0000000 --- a/apiGo/api/oauth/CustomClientStore.go +++ /dev/null @@ -1,57 +0,0 @@ -package oauth - -import ( - "gopkg.in/oauth2.v3" - "openmediacenter/apiGo/database/settings" -) - -type CustomClientStore struct { - oauth2.ClientStore -} - -type CustomClientInfo struct { - oauth2.ClientInfo - ID string - Secret string - Domain string - UserID string -} - -func NewCustomStore() oauth2.ClientStore { - s := new(CustomClientStore) - return s -} - -func (a *CustomClientStore) GetByID(id string) (oauth2.ClientInfo, error) { - password := settings.GetPassword() - // if password not set assign default password - if password == nil { - defaultpassword := "openmediacenter" - password = &defaultpassword - } - - clientinfo := CustomClientInfo{ - ID: "openmediacenter", - Secret: *password, - Domain: "http://localhost:8081", - UserID: "openmediacenter", - } - - return &clientinfo, nil -} - -func (a *CustomClientInfo) GetID() string { - return a.ID -} - -func (a *CustomClientInfo) GetSecret() string { - return a.Secret -} - -func (a *CustomClientInfo) GetDomain() string { - return a.Domain -} - -func (a *CustomClientInfo) GetUserID() string { - return a.UserID -} diff --git a/apiGo/api/oauth/Oauth.go b/apiGo/api/oauth/Oauth.go deleted file mode 100644 index 024b962..0000000 --- a/apiGo/api/oauth/Oauth.go +++ /dev/null @@ -1,62 +0,0 @@ -package oauth - -import ( - "gopkg.in/oauth2.v3" - "gopkg.in/oauth2.v3/errors" - "gopkg.in/oauth2.v3/manage" - "gopkg.in/oauth2.v3/server" - "gopkg.in/oauth2.v3/store" - "log" - "net/http" -) - -var srv *server.Server - -func InitOAuth() { - manager := manage.NewDefaultManager() - // token store - manager.MustTokenStorage(store.NewMemoryTokenStore()) - - // create new secretstore - clientStore := NewCustomStore() - manager.MapClientStorage(clientStore) - - srv = server.NewServer(server.NewConfig(), manager) - srv.SetClientInfoHandler(server.ClientFormHandler) - manager.SetRefreshTokenCfg(manage.DefaultRefreshTokenCfg) - - srv.SetInternalErrorHandler(func(err error) (re *errors.Response) { - log.Println("Internal Error:", err.Error()) - return - }) - - srv.SetResponseErrorHandler(func(re *errors.Response) { - log.Println("Response Error:", re.Error.Error()) - }) - - http.HandleFunc("/authorize", func(w http.ResponseWriter, r *http.Request) { - err := srv.HandleAuthorizeRequest(w, r) - if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) - } - }) - - http.HandleFunc("/token", func(w http.ResponseWriter, r *http.Request) { - err := srv.HandleTokenRequest(w, r) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - } - }) -} - -func ValidateToken(f func(rw http.ResponseWriter, req *http.Request, node int, tokenInfo *oauth2.TokenInfo), node int) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - tokeninfo, err := srv.ValidationBearerToken(r) - if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - - f(w, r, node, &tokeninfo) - } -} diff --git a/apiGo/go.mod b/apiGo/go.mod index 8c8f167..bb4b634 100644 --- a/apiGo/go.mod +++ b/apiGo/go.mod @@ -3,8 +3,10 @@ module openmediacenter/apiGo go 1.16 require ( + github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/go-sql-driver/mysql v1.5.0 github.com/pelletier/go-toml/v2 v2.0.0-beta.3 + golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 gopkg.in/oauth2.v3 v3.12.0 nhooyr.io/websocket v1.8.7 ) diff --git a/apiGo/go.sum b/apiGo/go.sum index 2427f80..79d3e8e 100644 --- a/apiGo/go.sum +++ b/apiGo/go.sum @@ -41,7 +41,6 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -50,7 +49,6 @@ github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= @@ -78,9 +76,7 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -125,6 +121,7 @@ github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FB github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= diff --git a/apiGo/main.go b/apiGo/main.go index 76507f1..d307415 100644 --- a/apiGo/main.go +++ b/apiGo/main.go @@ -5,6 +5,7 @@ import ( "log" "net/http" "openmediacenter/apiGo/api" + api2 "openmediacenter/apiGo/api/api" "openmediacenter/apiGo/config" "openmediacenter/apiGo/database" "openmediacenter/apiGo/static" @@ -35,7 +36,7 @@ func main() { // add the static files static.ServeStaticFiles() - api.ServerInit() + api2.ServerInit() fmt.Printf("OpenMediacenter server up and running on port %d\n", port) log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", port), nil)) diff --git a/src/utils/Api.ts b/src/utils/Api.ts index 5fb447d..55ba285 100644 --- a/src/utils/Api.ts +++ b/src/utils/Api.ts @@ -68,7 +68,7 @@ function generalAPICall( mytoken: string ): void { (async function (): Promise { - const response = await fetch(APIPREFIX + apinode, { + const response = await fetch(APIPREFIX + apinode + '/' + fd.action, { method: 'POST', body: JSON.stringify(fd), headers: new Headers({