Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GUI Features and Requirements #5

Open
zanix opened this issue Mar 8, 2016 · 12 comments
Open

GUI Features and Requirements #5

zanix opened this issue Mar 8, 2016 · 12 comments

Comments

@zanix
Copy link
Member

zanix commented Mar 8, 2016

This is a holder for all the requirements and features for msc-GUI. Later we will create tasks and maybe even use the milestone feature in GitHub to track this.

I'll start this list and then we can start categorizing them by importance. As we figure out what is more important we can limit this list to only what is absolutely needed for a 1.0 and assign features for later versions.

  • Communicate with mscs over REST using token auth
  • World list
  • Control servers
    • start/stop/restart
    • enable/disable
    • create/destroy
  • Login or other authentication
    • users and groups with access control
  • Backups
    • list/create/delete
    • Not sure if delete works since backups are incremental
    • Create tar.gz from any backup?
  • Server stats
    • CPU, memory, MC version, plugins, players online, whitelist, blacklist, ops
  • Settings view/set/update
    • global and per-world
@zanix zanix changed the title GUI 1.0 Requirements GUI Features and Requirements Mar 8, 2016
@sandain
Copy link
Member

sandain commented Mar 12, 2016

I've been doing some research on RESTful APIs, and I am beginning to come up to speed. If we want to stick with Perl, Mojolicious would probably be a whole lot better than trying to write something DIY like this. Mojolicious has theming support, has its own webserver so we don't necessarily need Apache, and it looks like it supports authentication as well.

If you guys would rather work with some other language like PHP or Python, that is fine with me.

@zanix
Copy link
Member Author

zanix commented Mar 12, 2016

The backend language doesn't matter all that much, the HTML/JS/CSS can and should be pretty separate from that. I also think setting up our own web service without having to rely on Apache or Nginx could be a good thing (less dependencies) and maybe some might not want a web server running on their Minecraft server.

All that said, I think mscs would be nice if it had a REST service within itself. Then we could do neat things like remote server control. That or we need the REST service as an additional layer so we have [mscs <-> msc-REST <-> msc-GUI], or for remote management [mscs <-> msc-REST <-> msc-REST <-> mscs]. Then again, maybe I'm getting ahead of myself.

@sandain
Copy link
Member

sandain commented Mar 13, 2016

Maybe this is more of a pain than it is worth, but I would like it better if our user facing solution would still function without JS. I use NoScript for safer web browsing, and nothing annoys me more than a web site that just feeds me a nonfunctional white screen or a garbled mess until I add the site to my whitelist.

To this end, it seems like we need to have all formatting logic server side. JS would only be used to make the page interactive without a page reload. A good example of what I am talking about would be the world menu. I could see JS grabbing the list of worlds and updating the menu, but I would prefer that the html presented by the server already have all of the worlds listed. This means we need a theming engine.

My question is: do we need two different webservers running (rest and gui), or would it be better if they were controlled by the same program? I think I see what you are talking about RE the remote management solution, but what does that provide that ssh or the gui wouldn't provide?

Edit: another thing to note is that not everyone will want to use the gui, so adding more bloat to mscs might be seen as a bad thing to some, meaning that [mscs <--> rest <--> gui] makes more sense to me than adding rest to mscs.

@sandain
Copy link
Member

sandain commented Mar 13, 2016

Let's see if we can come up with a list of nouns and verbs that we would need. Here is a RFC start:

  • http://server.com/msc/worlds
    • GET: return a JSON array of worlds.
  • http://server.com/msc/worlds/alpha
    • GET: return JSON hash containing the statistics for world alpha
    • POST: create world alpha (also need port and ip variables somehow)
    • DELETE: delete world alpha
  • http://server.com/msc/maps
    • GET: return a JSON array of worlds that have been mapped
  • http://server.com/msc/maps/alpha
    • GET: the Overviewer generated content for world alpha
    • POST: run Overviewer on world alpha
    • DELETE: delete the Overviewer generated content for world alpha

@zanix
Copy link
Member Author

zanix commented Mar 13, 2016

Maybe this is more of a pain than it is worth, but I would like it better if our user facing solution would still function without JS. I use NoScript for safer web browsing, and nothing annoys me more than a web site that just feeds me a nonfunctional white screen or a garbled mess until I add the site to my whitelist.

I don't mind JS myself but I do understand the desire to run NoScript. AJAX is nice for updating parts of content without reloads but we can make the site function without it.

To this end, it seems like we need to have all formatting logic server side. JS would only be used to make the page interactive without a page reload. A good example of what I am talking about would be the world menu. I could see JS grabbing the list of worlds and updating the menu, but I would prefer that the html presented by the server already have all of the worlds listed. This means we need a theming engine.

Exactly, first render has all the content already, JS just makes it interactive.

My question is: do we need two different webservers running (rest and gui), or would it be better if they were controlled by the same program? I think I see what you are talking about RE the remote management solution, but what does that provide that ssh or the gui wouldn't provide?

I don't think so. REST and the GUI could run on the same webserver. Having REST separate would just provide a different method for controlling mscs and we could have multi-mscs server control in the GUI and allow not having the GUI portion on the servers that don't need it.

Edit: another thing to note is that not everyone will want to use the gui, so adding more bloat to mscs might be seen as a bad thing to some, meaning that [mscs <--> rest <--> gui] makes more sense to me than adding rest to mscs.

Agreed, that is why I suggested msc-REST be separate. Keeps mscs more simple.

@sandain
Copy link
Member

sandain commented May 28, 2016

Anyone making any progress on this?

@zanix
Copy link
Member Author

zanix commented May 29, 2016

I haven't been able to touch it since I started a new job recently. Once I get into the grove there hopefully I can start contributing.

@Roflicide
Copy link
Member

Hi guys :)

Likewise, I've been very busy recently finishing up school. I will definitely start contributing soon as the summer arrives

@Roflicide
Copy link
Member

Although it's been more than a year since we've started discussing this, I definitely still want to do this. One of the things I've been looking into is flask, a popular, full-stack python web microframework that is well-documented and includes support for authentication and restful API's. It also seems to be more beginner friendly (for someone like me). If it's good with you guys, I'll start developing this using that framework.

Did we ever figure out if we wanted to include a database in MSCS for the rest API to communicate with? Or what's the alternative? (I suppose we could include a database inside of MSC-gui and have it query MSCS for updates, but that seems very complicated)

@zanix
Copy link
Member Author

zanix commented Jul 1, 2017

This project has been in the back of my head as well, I just wish I had time to devote to it. I'm not sure this would require a DB, except for maybe user profiles access control.

@sandain
Copy link
Member

sandain commented Apr 16, 2018

I played around with a new script today that uses a RESTful API and the Perl module Mojolicious. It is more performant than my CGI::Ajax-based script but is mostly functionally equivalent.

use strict;
use warnings;
use utf8;
use feature ':5.10';

use Mojolicious::Lite;

get '/' => sub {
  my $self = shift;
  $self->stash (enabled_worlds => &getEnabledWorlds);
  $self->stash (disabled_worlds => &getDisabledWorlds);
  $self->render (template => 'dashboard');
};

get '/worlds' => sub {
  my $self = shift;
  $self->stash (enabled_worlds => &getEnabledWorlds);
  $self->stash (disabled_worlds => &getDisabledWorlds);
  $self->render (template => 'worlds');
};

get '/worlds/:world' => sub {
  my $self = shift;
  my $world = $self->stash ('world');
  my $enabled = &getEnabledWorlds;
  my $disabled = &getDisabledWorlds;
  $self->stash (title => "MSC-GUI: $world");
  $self->stash (enabled_worlds => $enabled);
  $self->stash (disabled_worlds => $disabled);
  if ($world ~~ @{$enabled}) {
    my $backups = mscs ("list-backups", $world);
    my @query = split /\t/, mscs ("query", $world);
    $self->stash (backup_list      => $backups);
    $self->stash (query_motd       => $query[6]);
    $self->stash (query_gametype   => $query[8]);
    $self->stash (query_gameid     => $query[10]);
    $self->stash (query_version    => $query[12]);
    $self->stash (query_plugins    => $query[14]);
    $self->stash (query_map        => $query[16]);
    $self->stash (query_numplayers => $query[18]);
    $self->stash (query_maxplayers => $query[20]);
    $self->stash (query_hostport   => $query[22]);
    $self->stash (query_hostip     => $query[24]);
    $self->stash (query_players    => $query[29]);
    $self->render (template => 'enabled-world');
  }
  else {
    $self->render (template => 'disabled-world');
  }
};

app->start ('daemon', '-l', 'http://*:3000?reuse=1');





sub getEnabledWorlds {
  my $self = shift;
  my @worlds;
  foreach my $line (mscs ("ls enabled")) {
    if ($line =~ /^\s*(\w+):/) {
      push @worlds, $1;
    }
  }
  return \@worlds;
}

sub getDisabledWorlds {
  my $self = shift;
  my @worlds;
  foreach my $line (mscs ("ls disabled")) {
    if ($line =~ /^\s*(\w+):/) {
      push @worlds, $1;
    }
  }
  return \@worlds;
}

sub mscs {
  return `mscs @_`;
}

__DATA__

@@ dashboard.html.ep
% layout 'default';
<h1>Dashboard</h1>
<h2>Enabled Worlds:</h2>
<ul>
% foreach my $world (@{stash('enabled_worlds')}) {
  <li><a href="/worlds/<%= $world %>"><%= $world %></a></li>
% }
</ul>
<h2>Disabled Worlds:</h2>
<ul>
% foreach my $world (@{stash('disabled_worlds')}) {
  <li><a href="/worlds/<%= $world %>"><%= $world %></a></li>
% }
</ul>


@@ worlds.html.ep
% layout 'default';
<h2>Enabled Worlds:</h2>
<ul>
% foreach my $world (@{stash('enabled_worlds')}) {
  <li><%= $world %></li>
% }
</ul>
<h2>Disabled Worlds:</h2>
<ul>
% foreach my $world (@{stash('disabled_worlds')}) {
  <li><%= $world %></li>
% }
</ul>


@@ enabled-world.html.ep
% layout 'default';
<h1><%= $world %></h1>

<pre id="backup_list">
List of backups:

<%= $backup_list %>
</pre>

<pre id="query">
Query:

MOTD: <%= $query_motd %>
Game type: <%= $query_gametype %>
Game ID: <%= $query_gameid %>
Server Version: <%= $query_version %>
Server Plugins: <%= $query_plugins %>
Server Map: <%= $query_map %>
Number of players online: <%= $query_numplayers %>
Maximum players: <%= $query_maxplayers %>
Host port: <%= $query_hostport %>
Host IP: <%= $query_hostip %>
Player list: <%= $query_players %>
</pre>

<a href="http://localhost/maps/<%= $world %>/index.html"><img id="map" src="http://localhost/maps/<%= $world %>/normalrender/base.png" alt="Map of <%= $world %>"/></a>


@@ disabled-world.html.ep
% layout 'default';
<h1>Disabled world: <%= $world %></h1>


@@ layouts/default.html.ep
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='icon' type='image/x-icon' href='/favicon.ico'/>
<link rel='stylesheet' type='text/css' href='/stylesheet.css'/>
</head>
<body>
<div id='title_box'>
<img id='title_image' src='/title-image.png' alt='Title Image'/>
</div>
<div id='title'>Minecraft Server Control</div>
<div id='menu_box'>
<a id='msc_menu_dashboard' class='menu_item_active' href='/'>Dashboard</a>
% foreach my $world (@{stash('enabled_worlds')}) {
<a id='msc_menu_<%= $world %>' class='menu_item_active' href='/worlds/<%= $world %>'><%= $world %></a>
% }
% foreach my $world (@{stash('disabled_worlds')}) {
<a id='msc_menu_<%= $world %>' class='menu_item_inactive' href='/worlds/<%= $world %>'><%= $world %></a>
% }

</div>
<div id='content_box'><%= content %></div>
</body>
</html>

@sandain
Copy link
Member

sandain commented Jun 6, 2018

I posted a new version of the above script as Pull Request #7.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants