mirror of
https://github.com/OpenFactorioServerManager/factorio-server-manager.git
synced 2025-01-26 05:27:21 +02:00
save factorio-credentials server-sided
This commit is contained in:
parent
f8d5a78c09
commit
fe247a6958
1
.gitignore
vendored
1
.gitignore
vendored
@ -11,3 +11,4 @@ build/
|
||||
npm-debug.log
|
||||
.idea/
|
||||
/ui/package-lock.json
|
||||
factorio.auth
|
||||
|
@ -22,6 +22,7 @@ type Config struct {
|
||||
FactorioBinary string `json:"factorio_binary"`
|
||||
FactorioRconPort int `json:"rcon_port"`
|
||||
FactorioRconPass string `json:"rcon_pass"`
|
||||
FactorioCredentialsFile string `json:"factorio_credentials_file"`
|
||||
ServerIP string `json:"server_ip"`
|
||||
ServerPort string `json:"server_port"`
|
||||
MaxUploadSize int64 `json:"max_upload_size"`
|
||||
@ -82,6 +83,7 @@ func parseFlags() {
|
||||
config.FactorioConfigDir = filepath.Join(config.FactorioDir, "config")
|
||||
config.FactorioConfigFile = filepath.Join(config.FactorioDir, *factorioConfigFile)
|
||||
config.FactorioBinary = filepath.Join(config.FactorioDir, *factorioBinary)
|
||||
config.FactorioCredentialsFile = "./factorio.auth"
|
||||
config.MaxUploadSize = *factorioMaxUpload
|
||||
|
||||
if runtime.GOOS == "windows" {
|
||||
|
@ -119,11 +119,22 @@ func (mods *Mods) createMod(mod_name string, file_name string, file_rc io.Reader
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mods *Mods) downloadMod(username string, userKey string, url string, filename string, mod_id string) (error) {
|
||||
func (mods *Mods) downloadMod(url string, filename string, mod_id string) (error) {
|
||||
var err error
|
||||
|
||||
var credentials FactorioCredentials
|
||||
status, err := credentials.load()
|
||||
if err != nil {
|
||||
log.Printf("error loading credentials: %s", err)
|
||||
return err
|
||||
}
|
||||
if status == false {
|
||||
log.Printf("error: credentials are invalid")
|
||||
return errors.New("error: credentials are invalid")
|
||||
}
|
||||
|
||||
//download the mod from the mod portal api
|
||||
complete_url := "https://mods.factorio.com" + url + "?username=" + username + "&token=" + userKey
|
||||
complete_url := "https://mods.factorio.com" + url + "?username=" + credentials.Username + "&token=" + credentials.Userkey
|
||||
|
||||
response, err := http.Get(complete_url)
|
||||
if err != nil {
|
||||
@ -193,7 +204,7 @@ func (mods *Mods) uploadMod(header *multipart.FileHeader) (error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mods *Mods) updateMod(mod_name string, username string, userKey string, url string, filename string) error {
|
||||
func (mods *Mods) updateMod(mod_name string, url string, filename string) error {
|
||||
var err error
|
||||
|
||||
//err = mods.deleteMod(mod_name)
|
||||
@ -202,7 +213,7 @@ func (mods *Mods) updateMod(mod_name string, username string, userKey string, ur
|
||||
// return err
|
||||
//}
|
||||
|
||||
err = mods.downloadMod(username, userKey, url, filename, mod_name)
|
||||
err = mods.downloadMod(url, filename, mod_name)
|
||||
if err != nil {
|
||||
log.Printf("updateMod ... error when downloading the new Mod: %s", err)
|
||||
return err
|
||||
|
119
src/mods.go
119
src/mods.go
@ -21,27 +21,116 @@ type LoginErrorResponse struct {
|
||||
type LoginSuccessResponse struct {
|
||||
UserKey []string `json:""`
|
||||
}
|
||||
type FactorioCredentials struct {
|
||||
Username string `json:"username"`
|
||||
Userkey string `json:"userkey"`
|
||||
}
|
||||
|
||||
func (credentials *FactorioCredentials) save() error {
|
||||
var err error
|
||||
|
||||
credentials_json, err := json.Marshal(credentials)
|
||||
if err != nil {
|
||||
log.Printf("error mashalling the credentials: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(config.FactorioCredentialsFile, credentials_json, 0664)
|
||||
if err != nil {
|
||||
log.Printf("error on saving the credentials. %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (credentials *FactorioCredentials) load() (bool, error) {
|
||||
var err error
|
||||
|
||||
if _, err := os.Stat(config.FactorioCredentialsFile); os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
file_bytes, err := ioutil.ReadFile(config.FactorioCredentialsFile)
|
||||
if err != nil {
|
||||
credentials.del()
|
||||
log.Printf("error reading CredentialsFile: %s", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(file_bytes, credentials)
|
||||
if err != nil {
|
||||
credentials.del()
|
||||
log.Printf("error on unmarshal credentials_file: %s", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
if credentials.Userkey != "" && credentials.Username != "" {
|
||||
return true, nil
|
||||
} else {
|
||||
credentials.del()
|
||||
return false, errors.New("incredients incomplete")
|
||||
}
|
||||
}
|
||||
|
||||
func (credentials *FactorioCredentials) del() error {
|
||||
var err error
|
||||
|
||||
err = os.Remove(config.FactorioCredentialsFile)
|
||||
if err != nil {
|
||||
log.Printf("error delete the credentialfile: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//Log the user into factorio, so mods can be downloaded
|
||||
func getUserToken(username string, password string) (string, error, int) {
|
||||
resp, get_err := http.PostForm("https://auth.factorio.com/api-login",
|
||||
func factorioLogin(username string, password string) (string, error, int) {
|
||||
var err error
|
||||
|
||||
resp, err := http.PostForm("https://auth.factorio.com/api-login",
|
||||
url.Values{"require_game_ownership": {"true"}, "username": {username}, "password": {password}})
|
||||
if get_err != nil {
|
||||
log.Fatal(get_err)
|
||||
return "error", get_err, 500
|
||||
|
||||
if err != nil {
|
||||
log.Printf("error on logging in: %s", err)
|
||||
return "", err, resp.StatusCode
|
||||
}
|
||||
|
||||
//get the response-text
|
||||
text, err_io := ioutil.ReadAll(resp.Body)
|
||||
resp.Body.Close()
|
||||
defer resp.Body.Close()
|
||||
|
||||
text_string := string(text)
|
||||
|
||||
if err_io != nil {
|
||||
log.Fatal(err_io)
|
||||
return "error", err_io, resp.StatusCode
|
||||
body_bytes, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Printf("error on reading resp.Body: %s", err)
|
||||
return "", err, http.StatusInternalServerError
|
||||
}
|
||||
|
||||
return text_string, nil, resp.StatusCode
|
||||
body_string := string(body_bytes)
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
log.Println("error Statuscode not 200")
|
||||
return body_string, errors.New("Statuscode not 200"), resp.StatusCode
|
||||
}
|
||||
|
||||
var success_response []string
|
||||
err = json.Unmarshal(body_bytes, &success_response)
|
||||
if err != nil {
|
||||
log.Printf("error on unmarshal body: %s", err)
|
||||
return err.Error(), err, http.StatusInternalServerError
|
||||
}
|
||||
|
||||
credentials := FactorioCredentials{
|
||||
Username: username,
|
||||
Userkey: success_response[0],
|
||||
}
|
||||
|
||||
err = credentials.save()
|
||||
if err != nil {
|
||||
log.Printf("error saving the credentials. %s", err)
|
||||
return err.Error(), err, http.StatusInternalServerError
|
||||
}
|
||||
|
||||
return "", nil, http.StatusOK
|
||||
}
|
||||
|
||||
|
||||
@ -79,7 +168,7 @@ func getModDetails(modId string) (string, error, int) {
|
||||
resp, err := http.Get(new_link)
|
||||
|
||||
if err != nil {
|
||||
return "error", err, 500
|
||||
return "error", err, http.StatusInternalServerError
|
||||
}
|
||||
|
||||
//get the response-text
|
||||
|
@ -41,7 +41,7 @@ func listInstalledModsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
// Returns JSON response with the userKey or the error-message
|
||||
// Returns JSON response with success or error-message
|
||||
func LoginFactorioModPortal(w http.ResponseWriter, r *http.Request) {
|
||||
var err error
|
||||
resp := JSONResponse{
|
||||
@ -53,13 +53,39 @@ func LoginFactorioModPortal(w http.ResponseWriter, r *http.Request) {
|
||||
username := r.FormValue("username")
|
||||
password := r.FormValue("password")
|
||||
|
||||
var statusCode int
|
||||
resp.Data, err, statusCode = getUserToken(username, password)
|
||||
login_status, err, statusCode := factorioLogin(username, password)
|
||||
if login_status == "" && err == nil {
|
||||
resp.Data = true
|
||||
}
|
||||
|
||||
w.WriteHeader(statusCode)
|
||||
|
||||
if err != nil {
|
||||
w.WriteHeader(500)
|
||||
resp.Data = fmt.Sprintf("Error in getUserToken or LoginFactorioModPortal handler: %s", err)
|
||||
if err := json.NewEncoder(w).Encode(resp); err != nil {
|
||||
log.Printf("Error in Factorio-Login: %s", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
resp.Success = true
|
||||
|
||||
if err := json.NewEncoder(w).Encode(resp); err != nil {
|
||||
log.Printf("Error in Factorio-Login: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func LoginstatusFactorioModPortal(w http.ResponseWriter, r *http.Request) {
|
||||
var err error
|
||||
resp := JSONResponse{
|
||||
Success: false,
|
||||
}
|
||||
|
||||
var credentials FactorioCredentials
|
||||
resp.Data, err = credentials.load()
|
||||
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
resp.Data = fmt.Sprintf("Error in getUserToken or LoginFactorioModPortal handler: %s", err)
|
||||
if err := json.NewEncoder(w).Encode(resp); err != nil {
|
||||
log.Printf("Error in Factorio-Login: %s", err)
|
||||
@ -125,7 +151,6 @@ func ModPortalDetailsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(statusCode)
|
||||
|
||||
if err != nil {
|
||||
w.WriteHeader(500)
|
||||
resp.Data = fmt.Sprintf("Error in searchModPortal: %s", err)
|
||||
if err := json.NewEncoder(w).Encode(resp); err != nil {
|
||||
log.Printf("Error in searchModPortal: %s", err)
|
||||
@ -149,15 +174,13 @@ func ModPortalInstallHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json;charset=UTF-8")
|
||||
|
||||
//Get Data out of the request
|
||||
username := r.FormValue("username")
|
||||
userKey := r.FormValue("userKey")
|
||||
downloadUrl := r.FormValue("link")
|
||||
filename := r.FormValue("filename")
|
||||
mod_name := r.FormValue("modName")
|
||||
|
||||
mods, err := newMods(config.FactorioModsDir)
|
||||
if err == nil {
|
||||
err = mods.downloadMod(username, userKey, downloadUrl, filename, mod_name)
|
||||
err = mods.downloadMod(downloadUrl, filename, mod_name)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@ -253,14 +276,12 @@ func UpdateModHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
//Get Data out of the request
|
||||
mod_name := r.FormValue("mod_name")
|
||||
username := r.FormValue("username")
|
||||
user_key := r.FormValue("userKey")
|
||||
download_url := r.FormValue("downloadUrl")
|
||||
file_name := r.FormValue("filename")
|
||||
|
||||
mods, err := newMods(config.FactorioModsDir)
|
||||
if err == nil {
|
||||
err = mods.updateMod(mod_name, username, user_key, download_url, file_name)
|
||||
err = mods.updateMod(mod_name, download_url, file_name)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@ -580,8 +601,6 @@ func ModPackUpdateModHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
//Get Data out of the request
|
||||
mod_name := r.FormValue("mod_name")
|
||||
username := r.FormValue("username")
|
||||
user_key := r.FormValue("userKey")
|
||||
download_url := r.FormValue("downloadUrl")
|
||||
file_name := r.FormValue("filename")
|
||||
mod_pack_name := r.FormValue("mod_pack_name")
|
||||
@ -589,7 +608,7 @@ func ModPackUpdateModHandler(w http.ResponseWriter, r *http.Request) {
|
||||
mod_pack_map, err := newModPackMap()
|
||||
if err == nil {
|
||||
if mod_pack_map.checkModPackExists(mod_pack_name){
|
||||
err = mod_pack_map[mod_pack_name].Mods.updateMod(mod_name, username, user_key, download_url, file_name)
|
||||
err = mod_pack_map[mod_pack_name].Mods.updateMod(mod_name, download_url, file_name)
|
||||
} else {
|
||||
err = errors.New("ModPack " + mod_pack_name + "does not exist")
|
||||
}
|
||||
|
@ -158,6 +158,11 @@ var apiRoutes = Routes{
|
||||
"POST",
|
||||
"/mods/factorio/login",
|
||||
LoginFactorioModPortal,
|
||||
}, {
|
||||
"LoginstatusFactorioModPortal",
|
||||
"POST",
|
||||
"/mods/factorio/status",
|
||||
LoginstatusFactorioModPortal,
|
||||
}, {
|
||||
"SearchModPortal",
|
||||
"GET",
|
||||
|
@ -103,6 +103,7 @@ ModOverview.propTypes = {
|
||||
deleteMod: React.PropTypes.func.isRequired,
|
||||
updateMod: React.PropTypes.func.isRequired,
|
||||
uploadModSuccessHandler: React.PropTypes.func.isRequired,
|
||||
logged_in: React.PropTypes.bool.isRequired,
|
||||
|
||||
modContentClass: instanceOfModsContent.isRequired,
|
||||
};
|
||||
|
@ -263,7 +263,7 @@ class ModPackOverview extends React.Component {
|
||||
modPackUpdateModHandler(e, toggleUpdateStatus, removeVersionAvailableStatus) {
|
||||
e.preventDefault();
|
||||
|
||||
if(!this.props.modContentClass.state.userKey) {
|
||||
if(!this.props.modContentClass.state.logged_in) {
|
||||
swal({
|
||||
type: "error",
|
||||
title: "Update failed",
|
||||
@ -291,8 +291,6 @@ class ModPackOverview extends React.Component {
|
||||
url: "/api/mods/packs/mod/update",
|
||||
method: "POST",
|
||||
data: {
|
||||
username: this.props.modContentClass.state.username,
|
||||
userKey: this.props.modContentClass.state.userKey,
|
||||
downloadUrl: download_url,
|
||||
filename: filename,
|
||||
mod_name: modname,
|
||||
|
@ -3,7 +3,7 @@ import ModFoundOverview from './ModFoundOverview.jsx';
|
||||
|
||||
class ModSearch extends React.Component {
|
||||
render() {
|
||||
if(this.props.userKey) {
|
||||
if(this.props.logged_in) {
|
||||
return (
|
||||
<div className="box-body">
|
||||
<form onSubmit={this.props.submitSearchMod}>
|
||||
@ -43,7 +43,7 @@ class ModSearch extends React.Component {
|
||||
|
||||
ModSearch.propTypes = {
|
||||
submitSearchMod: React.PropTypes.func.isRequired,
|
||||
userKey: React.PropTypes.string.isRequired,
|
||||
logged_in: React.PropTypes.bool.isRequired,
|
||||
submitFactorioLogin: React.PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
|
@ -18,14 +18,14 @@ class ModsContent extends React.Component {
|
||||
this.uploadModSuccessHandler = this.uploadModSuccessHandler.bind(this);
|
||||
|
||||
this.state = {
|
||||
username: sessionStorage.getItem("username") || "",
|
||||
userKey: sessionStorage.getItem("userKey") || "",
|
||||
logged_in: false,
|
||||
installedMods: [],
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.loadModList();
|
||||
this.checkLoginState();
|
||||
}
|
||||
|
||||
loadModList() {
|
||||
@ -45,7 +45,6 @@ class ModsContent extends React.Component {
|
||||
e.preventDefault();
|
||||
|
||||
let $form = $(e.target);
|
||||
let username = $form.find('input[name=username]').val();
|
||||
|
||||
$.ajax({
|
||||
url: "/api/mods/factorio/login",
|
||||
@ -58,27 +57,38 @@ class ModsContent extends React.Component {
|
||||
type: "success"
|
||||
});
|
||||
|
||||
let user_key = (JSON.parse(data.data))[0];
|
||||
|
||||
sessionStorage.setItem("username", username);
|
||||
sessionStorage.setItem("userKey", user_key);
|
||||
|
||||
this.setState({
|
||||
"username": username,
|
||||
"userKey": user_key
|
||||
"logged_in": data.data
|
||||
});
|
||||
},
|
||||
error: (jqXHR) => {
|
||||
let json_data = JSON.parse(jqXHR.responseJSON.data);
|
||||
|
||||
swal({
|
||||
title: json_data.message,
|
||||
title: jqXHR.responseJSON.data,
|
||||
type: "error"
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
checkLoginState() {
|
||||
let this_class = this;
|
||||
$.ajax({
|
||||
url: "/api/mods/factorio/status",
|
||||
method: "POST",
|
||||
dataType: "json",
|
||||
success: (data) => {
|
||||
this_class.setState({
|
||||
"logged_in": data.data
|
||||
})
|
||||
},
|
||||
error: (jqXHR) => {
|
||||
let json_data = JSON.parse(jqXHR.responseJSON.data);
|
||||
|
||||
console.log("error checking login status", json_data)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
loadDownloadListSwalHandler() {
|
||||
let $checked_input = $('input[name=version]:checked');
|
||||
let link = $checked_input.data("link");
|
||||
@ -92,8 +102,6 @@ class ModsContent extends React.Component {
|
||||
url: "/api/mods/install",
|
||||
dataType: "JSON",
|
||||
data: {
|
||||
username: this.state.username,
|
||||
userKey: this.state.userKey,
|
||||
link: link,
|
||||
filename: filename,
|
||||
modName: mod_name
|
||||
@ -286,7 +294,7 @@ class ModsContent extends React.Component {
|
||||
updateModHandler(e, toggleUpdateStatus, removeVersionAvailableStatus) {
|
||||
e.preventDefault();
|
||||
|
||||
if(!this.state.userKey) {
|
||||
if(!this.state.logged_in) {
|
||||
swal({
|
||||
type: "error",
|
||||
title: "Update failed",
|
||||
@ -312,8 +320,6 @@ class ModsContent extends React.Component {
|
||||
url: "/api/mods/update",
|
||||
method: "POST",
|
||||
data: {
|
||||
username: this.state.username,
|
||||
userKey: this.state.userKey,
|
||||
downloadUrl: download_url,
|
||||
filename: filename,
|
||||
mod_name: modname,
|
||||
|
Loading…
x
Reference in New Issue
Block a user