added view and handler for login

This commit is contained in:
majormjr 2016-04-29 23:59:13 -04:00
parent b0b3f43b30
commit 0de9c880e5
22 changed files with 310 additions and 50 deletions

1
.gitignore vendored
View File

@ -1,4 +1,5 @@
node_modules/
bundle.js
factorio-server-manager
auth.level-db
*.exe

View File

@ -35,6 +35,6 @@
<!-- AdminLTE App -->
<script src="./dist/dist/js/app.min.js"></script>
<!-- Main application -->
<script src="bundle.js"></script>
<script src="./bundle.js"></script>
</body>
</html>

22
auth.go
View File

@ -2,6 +2,7 @@ package main
import (
"log"
"os"
"github.com/apexskier/httpauth"
)
@ -11,10 +12,29 @@ type AuthHTTP struct {
aaa httpauth.Authorizer
}
type User struct {
Username string
Password string
Role string
}
func initAuth() *AuthHTTP {
return &AuthHTTP{}
}
func (auth *AuthHTTP) createAuthDb(backendFile string) error {
var err error
os.Mkdir(backendFile, 0755)
auth.backend, err = httpauth.NewLeveldbAuthBackend(backendFile)
if err != nil {
log.Printf("Error creating Auth backend: %s", err)
return err
}
return nil
}
func (auth *AuthHTTP) createRoles() {
var err error
roles := make(map[string]httpauth.Role)
@ -27,7 +47,7 @@ func (auth *AuthHTTP) createRoles() {
}
}
func (auth *AuthHTTP) createUser(username, role, password, email string) error {
func (auth *AuthHTTP) createUser(username, password, role, email string) error {
user := httpauth.UserData{Username: username, Role: role, Email: email}
err := auth.backend.SaveUser(user)
if err != nil {

BIN
auth.leveldb/000004.ldb Normal file

Binary file not shown.

BIN
auth.leveldb/000007.ldb Normal file

Binary file not shown.

BIN
auth.leveldb/000012.ldb Normal file

Binary file not shown.

BIN
auth.leveldb/000015.ldb Normal file

Binary file not shown.

BIN
auth.leveldb/000020.ldb Normal file

Binary file not shown.

BIN
auth.leveldb/000023.ldb Normal file

Binary file not shown.

BIN
auth.leveldb/000028.ldb Normal file

Binary file not shown.

BIN
auth.leveldb/000029.log Normal file

Binary file not shown.

1
auth.leveldb/CURRENT Normal file
View File

@ -0,0 +1 @@
MANIFEST-000030

0
auth.leveldb/LOCK Normal file
View File

149
auth.leveldb/LOG Normal file
View File

@ -0,0 +1,149 @@
=============== Apr 29, 2016 (EDT) ===============
23:19:38.770534 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
23:19:38.771110 db@open opening
23:19:38.775638 version@stat F·[] S·0B[] Sc·[]
23:19:38.783797 db@janitor F·2 G·0
23:19:38.783861 db@open done T·12.719123ms
23:19:38.783898 db@close closing
23:19:38.783970 db@close done T·67.905µs
=============== Apr 29, 2016 (EDT) ===============
23:19:38.784076 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
23:19:38.784282 version@stat F·[] S·0B[] Sc·[]
23:19:38.784309 db@open opening
23:19:38.784395 journal@recovery F·1
23:19:38.784714 journal@recovery recovering @1
23:19:38.786680 version@stat F·[] S·0B[] Sc·[]
23:19:38.789225 db@janitor F·2 G·0
23:19:38.789262 db@open done T·4.934329ms
23:19:38.789423 db@close closing
23:19:38.789522 db@close done T·96.606µs
=============== Apr 29, 2016 (EDT) ===============
23:19:38.926567 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
23:19:38.926753 version@stat F·[] S·0B[] Sc·[]
23:19:38.926771 db@open opening
23:19:38.926820 journal@recovery F·1
23:19:38.929753 journal@recovery recovering @2
23:19:38.933599 memdb@flush created L0@4 N·1 S·190B "htt..ata,v1":"htt..ata,v1"
23:19:38.936658 version@stat F·[1] S·190B[190B] Sc·[0.25]
23:19:38.937105 db@janitor F·3 G·0
23:19:38.937125 db@open done T·10.343223ms
23:19:38.937228 db@close closing
23:19:38.937260 db@close done T·71.925µs
=============== Apr 29, 2016 (EDT) ===============
23:36:25.541425 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
23:36:25.542263 version@stat F·[1] S·190B[190B] Sc·[0.25]
23:36:25.542306 db@open opening
23:36:25.542467 journal@recovery F·1
23:36:25.543972 journal@recovery recovering @5
23:36:25.556094 memdb@flush created L0@7 N·1 S·272B "htt..ata,v3":"htt..ata,v3"
23:36:25.557698 version@stat F·[2] S·462B[462B] Sc·[0.50]
23:36:25.560241 db@janitor F·4 G·0
23:36:25.560352 db@open done T·18.008692ms
23:36:25.560779 db@close closing
23:36:25.560989 db@close done T·192.676µs
=============== Apr 29, 2016 (EDT) ===============
23:36:25.561205 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
23:36:25.561634 version@stat F·[2] S·462B[462B] Sc·[0.50]
23:36:25.561696 db@open opening
23:36:25.561902 journal@recovery F·1
23:36:25.564982 journal@recovery recovering @8
23:36:25.568373 version@stat F·[2] S·462B[462B] Sc·[0.50]
23:36:25.569870 db@janitor F·4 G·0
23:36:25.569935 db@open done T·8.212765ms
23:36:25.570088 db@close closing
23:36:25.570208 db@close done T·110.318µs
=============== Apr 29, 2016 (EDT) ===============
23:36:25.752860 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
23:36:25.753038 version@stat F·[2] S·462B[462B] Sc·[0.50]
23:36:25.753053 db@open opening
23:36:25.753114 journal@recovery F·1
23:36:25.754012 journal@recovery recovering @10
23:36:25.757428 memdb@flush created L0@12 N·1 S·190B "htt..ata,v5":"htt..ata,v5"
23:36:25.760126 version@stat F·[3] S·652B[652B] Sc·[0.75]
23:36:25.761194 db@janitor F·5 G·0
23:36:25.761232 db@open done T·8.167192ms
23:36:25.761337 db@close closing
23:36:25.761419 db@close done T·80.195µs
=============== Apr 29, 2016 (EDT) ===============
23:43:57.915266 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
23:43:57.915962 version@stat F·[3] S·652B[652B] Sc·[0.75]
23:43:57.916007 db@open opening
23:43:57.916225 journal@recovery F·1
23:43:57.917459 journal@recovery recovering @13
23:43:57.924923 memdb@flush created L0@15 N·1 S·272B "htt..ata,v7":"htt..ata,v7"
23:43:57.925592 version@stat F·[4] S·924B[924B] Sc·[1.00]
23:43:57.928233 db@janitor F·6 G·0
23:43:57.928308 db@open done T·12.260507ms
23:43:57.928497 table@compaction L0·4 -> L1·0 S·924B Q·8
23:43:57.928727 db@close closing
23:43:57.928863 db@close done T·131.622µs
=============== Apr 29, 2016 (EDT) ===============
23:43:57.928972 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
23:43:57.929207 version@stat F·[4] S·924B[924B] Sc·[1.00]
23:43:57.929238 db@open opening
23:43:57.929370 journal@recovery F·1
23:43:57.932077 journal@recovery recovering @16
23:43:57.935691 version@stat F·[4] S·924B[924B] Sc·[1.00]
23:43:57.937241 db@janitor F·6 G·0
23:43:57.937297 db@open done T·8.038595ms
23:43:57.937455 table@compaction L0·4 -> L1·0 S·924B Q·8
23:43:57.937500 table@build exiting
23:43:57.937480 db@close closing
23:43:57.937612 db@close done T·126.927µs
=============== Apr 29, 2016 (EDT) ===============
23:43:58.109650 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
23:43:58.109851 version@stat F·[4] S·924B[924B] Sc·[1.00]
23:43:58.109876 db@open opening
23:43:58.109948 journal@recovery F·1
23:43:58.110915 journal@recovery recovering @18
23:43:58.116332 memdb@flush created L0@20 N·1 S·190B "htt..ata,v9":"htt..ata,v9"
23:43:58.118317 version@stat F·[5] S·1KiB[1KiB] Sc·[1.25]
23:43:58.119611 db@janitor F·7 G·0
23:43:58.119681 db@open done T·9.784011ms
23:43:58.119836 db@close closing
23:43:58.119856 table@compaction L0·5 -> L1·0 S·1KiB Q·10
23:43:58.119872 table@build exiting
23:43:58.119894 db@close done T·57.084µs
=============== Apr 29, 2016 (EDT) ===============
23:56:56.871481 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
23:56:56.871853 version@stat F·[5] S·1KiB[1KiB] Sc·[1.25]
23:56:56.871877 db@open opening
23:56:56.872001 journal@recovery F·1
23:56:56.873483 journal@recovery recovering @21
23:56:56.876720 memdb@flush created L0@23 N·1 S·272B "htt..ata,v11":"htt..ata,v11"
23:56:56.877379 version@stat F·[6] S·1KiB[1KiB] Sc·[1.50]
23:56:56.878820 db@janitor F·8 G·0
23:56:56.878905 db@open done T·6.998044ms
23:56:56.879728 table@compaction L0·6 -> L1·0 S·1KiB Q·12
23:56:56.880938 db@close closing
23:56:56.884410 table@build created L1@26 N·1 S·272B "htt..ata,v11":"htt..ata,v11"
23:56:56.884434 table@build exiting
23:56:56.884444 table@build revert @26
23:56:56.884615 db@close done T·3.667859ms
=============== Apr 29, 2016 (EDT) ===============
23:56:56.884716 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
23:56:56.884903 version@stat F·[6] S·1KiB[1KiB] Sc·[1.50]
23:56:56.884925 db@open opening
23:56:56.885023 journal@recovery F·1
23:56:56.886670 journal@recovery recovering @24
23:56:56.888161 version@stat F·[6] S·1KiB[1KiB] Sc·[1.50]
23:56:56.888611 db@janitor F·8 G·0
23:56:56.888648 db@open done T·3.709385ms
23:56:56.889258 table@compaction L0·6 -> L1·0 S·1KiB Q·12
23:56:56.889267 db@close closing
23:56:56.889272 table@build exiting
23:56:56.889305 db@close done T·36.664µs
=============== Apr 29, 2016 (EDT) ===============
23:56:56.993236 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
23:56:56.993379 version@stat F·[6] S·1KiB[1KiB] Sc·[1.50]
23:56:56.993392 db@open opening
23:56:56.993478 journal@recovery F·1
23:56:56.994592 journal@recovery recovering @26
23:56:56.999533 memdb@flush created L0@28 N·1 S·190B "htt..ata,v13":"htt..ata,v13"
23:56:57.000615 version@stat F·[7] S·1KiB[1KiB] Sc·[1.75]
23:56:57.001511 db@janitor F·9 G·0
23:56:57.001532 db@open done T·8.13046ms
23:56:57.001590 db@close closing
23:56:57.001631 table@compaction L0·7 -> L1·0 S·1KiB Q·15
23:56:57.001646 table@build exiting
23:56:57.001668 db@close done T·76.788µs

Binary file not shown.

View File

@ -561,3 +561,41 @@ func CheckServer(w http.ResponseWriter, r *http.Request) {
}
}
}
func LoginUser(w http.ResponseWriter, r *http.Request) {
resp := JSONResponse{
Success: false,
}
w.Header().Set("Content-Type", "application/json;charset=UTF-8")
switch r.Method {
case "GET":
log.Printf("GET not supported for login handler")
resp.Data = "Unsupported method"
resp.Success = false
if err := json.NewEncoder(w).Encode(resp); err != nil {
log.Printf("Error listing mods: %s", err)
}
case "POST":
var user User
body, err := ioutil.ReadAll(r.Body)
if err != nil {
log.Printf("Error in starting factorio server handler body: %s", err)
return
}
log.Printf("Logging in user: %v", string(body))
err = json.Unmarshal(body, &user)
if err != nil {
log.Printf("Error unmarshaling server settings JSON: %s", err)
return
}
fmt.Println(user)
}
//if err := Auth.aaa.Login(w, r, username, password, "/")
}

View File

@ -47,7 +47,6 @@ func loadServerConfig(f string) {
decoder := json.NewDecoder(file)
err = decoder.Decode(&config)
fmt.Println(config.Password)
parseFlags()
}
@ -78,7 +77,12 @@ func main() {
FactorioServ = initFactorio()
Auth = initAuth()
Auth.createAuthDb(config.DatabaseFile)
Auth.createRoles()
err := Auth.createUser(config.Username, config.Password, "admin", "")
if err != nil {
log.Printf("Error creating user: %s", err)
}
router := NewRouter()

View File

@ -31,7 +31,7 @@ func NewRouter() *mux.Router {
s.Methods(route.Method).
Path(route.Pattern).
Name(route.Name).
Handler(CheckSession(route.HandlerFunc))
Handler(route.HandlerFunc)
}
// Serves the frontend application from the app directory
@ -68,7 +68,6 @@ func NewRouter() *mux.Router {
// Middleware returns a http.HandlerFunc which authenticates the users request
func CheckSession(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Printf("%+v", Auth.aaa)
if err := Auth.aaa.Authorize(w, r, true); err != nil {
log.Printf("Unauthenticated request %s %s %s", r.Method, r.Host, r.RequestURI)
http.Redirect(w, r, "/login", http.StatusSeeOther)
@ -166,5 +165,10 @@ var apiRoutes = Routes{
"GET",
"/server/status",
CheckServer,
}, {
"LoginUser",
"POST",
"/login",
LoginUser,
},
}

View File

@ -1,4 +1,5 @@
import React from 'react';
import {browserHistory} from 'react-router';
import Header from './components/Header.jsx';
import Sidebar from './components/Sidebar.jsx';
import Footer from './components/Footer.jsx';
@ -15,7 +16,14 @@ class App extends React.Component {
serverRunning: "stopped",
serverStatus: {},
saves: [],
loggedIn: false,
loggedIn: true,
}
}
// Check if state.loggedIn is true, if so continue, else redirect to /login page.
componentWillMount() {
if (!this.state.loggedIn) {
browserHistory.push("/login");
}
}

View File

@ -2,53 +2,86 @@ import React from 'react';
import {IndexLink} from 'react-router';
class LoginContent extends React.Component {
constructor(props) {
super(props)
this.loginUser = this.loginUser.bind(this);
}
componentDidMount() {
console.log(this.state);
}
loginUser(e) {
e.preventDefault();
console.log(this)
let user = {
username: this.refs.username.value,
password: this.refs.password.value,
}
$.ajax({
type: "POST",
url: "/api/login",
dataType: "json",
data: JSON.stringify(user),
success: (resp) => {
console.log(resp)
}
})
}
render() {
return(
<div className="wrapper">
<div className="content-wrapper">
<section className="content-header">
<h1>
Login
<small>Login to manage Factorio</small>
</h1>
</section>
<section className="content">
<div className="container center-block">
<div className="row">
<div className="login-box-body">
<p className="login-box-msg">Sign in to start your session</p>
<div className="col-xs-6">
<div className="center-block">
<section className="content-header">
<h1>
Login
<small>Login to manage Factorio</small>
</h1>
</section>
<form action="">
<div className="form-group has-feedback">
<input type="email" className="form-control" placeholder="Email" />
<span className="fa fa-envelope form-control-feedback"></span>
</div>
<div className="form-group has-feedback">
<input type="password" className="form-control" placeholder="Password" />
<span className="fa fa-lock form-control-feedback"></span>
</div>
<div className="row">
<div className="col-xs-8">
<div className="checkbox">
<label className="">
<div className="" aria-checked="false" aria-disabled="false" style={{position: "relative"}}>
<input type="checkbox"/>
</div> Remember Me
</label>
<section className="content">
<div className="row">
<div className="login-box-body">
<form onSubmit={this.loginUser}>
<div className="form-group has-feedback">
<input type="text" ref="username" className="form-control" placeholder="Username" />
<span className="fa fa-envelope form-control-feedback"></span>
</div>
</div>
<div className="col-xs-4">
<button type="submit" className="btn btn-primary btn-block btn-flat">Sign In</button>
</div>
</div>
</form>
<div className="form-group has-feedback">
<input type="password" ref="password" className="form-control" placeholder="Password" />
<span className="fa fa-lock form-control-feedback"></span>
</div>
<div className="row">
<div className="col-xs-8">
<div className="checkbox">
<label className="">
<div className="" aria-checked="false" aria-disabled="false" style={{position: "relative"}}>
<input type="checkbox"/>
</div> Remember Me
</label>
</div>
</div>
</div>
<div className="row">
<div className="col-xs-4">
<button type="submit" className="btn btn-primary btn-block btn-flat">Sign In</button>
</div>
</div>
</form>
<a href="#">I forgot my password</a><br />
</div>
<a href="#">I forgot my password</a><br />
</div>
</div>
</section>
</div>
</div>
</div>
</section>
</div>
</div>
)
}
}

View File

@ -5,6 +5,7 @@ class ServerCtl extends React.Component {
super(props);
this.startServer = this.startServer.bind(this);
this.stopServer = this.stopServer.bind(this);
this.incrementAutosave = this.incrementAutosave.bind(this);
this.decrementAutosave = this.decrementAutosave.bind(this);
@ -214,17 +215,15 @@ class ServerCtl extends React.Component {
<div className="checkbox">
<label for="autoPause">
<input id="autoPause" ref="autoPause" type="checkbox" onClick={this.toggleAutoPause} />
Disable auto Pause when no players connected
Disable auto pause when no players connected
</label>
</div>
<div className="checkbox">
<label for="p2p">
<input id="p2p" ref="p2p" type="checkbox" onClick={this.toggleP2P} />
Peer to peer connection method
</label>
</div>
<div className="checkbox">
<label for="allowCmd">
<input id="allowCmd" ref="allowCmd" type="checkbox" onClick={this.toggleAllowCmd} />

View File

@ -9,11 +9,14 @@ import ConfigContent from './App/components/ConfigContent.jsx';
import LoginContent from './App/components/LoginContent.jsx';
import Index from './App/components/Index.jsx';
var loggedIn = false
ReactDOM.render((
<Router history={browserHistory}>
<Route path="/login" component={LoginContent}/>
<Route path="/" component={App}>
<Route path="/login" component={LoginContent} loggedIn={loggedIn}/>
<Route path="/" component={App} loggedIn={loggedIn}>
<IndexRoute component={Index}/>
<Route path="/server" component={Index}/>
<Route path="/mods" component={ModsContent}/>
<Route path="/logs" component={LogsContent}/>
<Route path="/saves" component={SavesContent}/>