save factorio-credentials server-sided

This commit is contained in:
knoxfighter 2017-09-29 15:39:37 +02:00
parent f8d5a78c09
commit fe247a6958
10 changed files with 188 additions and 56 deletions

1
.gitignore vendored
View File

@ -11,3 +11,4 @@ build/
npm-debug.log
.idea/
/ui/package-lock.json
factorio.auth

View File

@ -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" {

View File

@ -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

View File

@ -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

View File

@ -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")
}

View File

@ -158,6 +158,11 @@ var apiRoutes = Routes{
"POST",
"/mods/factorio/login",
LoginFactorioModPortal,
}, {
"LoginstatusFactorioModPortal",
"POST",
"/mods/factorio/status",
LoginstatusFactorioModPortal,
}, {
"SearchModPortal",
"GET",

View File

@ -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,
};

View File

@ -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,

View File

@ -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
}

View File

@ -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,