diff options
Diffstat (limited to 'pyload/web')
23 files changed, 414 insertions, 177 deletions
| diff --git a/pyload/web/api_app.py b/pyload/web/api_app.py index 9370e671f..39747d5ea 100644 --- a/pyload/web/api_app.py +++ b/pyload/web/api_app.py @@ -13,6 +13,30 @@ from pyload.Api import ExceptionObject  from pyload.remote.json_converter import loads, dumps, BaseEncoder  from pyload.utils import remove_chars +# used for gzip compression +try: +    import gzip +    from cStringIO import StringIO +except ImportError: +    gzip = None +    StringIO = None + +# gzips response if supported +def json_response(obj): +    accept = 'gzip' in request.headers.get('Accept-Encoding', '') +    result = dumps(obj) +    # don't compress small string +    if gzip and accept and len(result) > 500: +        response.headers['Vary'] = 'Accept-Encoding' +        response.headers['Content-Encoding'] = 'gzip' +        zbuf = StringIO() +        zfile = gzip.GzipFile(mode='wb', compresslevel=6, fileobj=zbuf) +        zfile.write(result) +        zfile.close() +        return zbuf.getvalue() + +    return result +  # returns http error  def error(code, msg): @@ -78,7 +102,7 @@ def call_api(func, args=""):          result = getattr(api, func)(*args, **kwargs)          # null is invalid json response          if result is None: result = True -        return dumps(result) +        return json_response(result)      except ExceptionObject, e:          return error(400, e.message) @@ -98,7 +122,7 @@ def login():      user = PYLOAD.checkAuth(username, password, request.environ.get('REMOTE_ADDR', None))      if not user: -        return dumps(False) +        return json_response(False)      s = set_session(request, user) @@ -116,7 +140,7 @@ def login():      if request.params.get('user', None):          return dumps(result) -    return dumps(sid) +    return json_response(sid)  @route("/api/logout") @@ -127,4 +151,4 @@ def logout():      s = request.environ.get('beaker.session')      s.delete() -    return dumps(True) +    return json_response(True) diff --git a/pyload/web/app/index.html b/pyload/web/app/index.html index bf75d40ed..98e1bf233 100644 --- a/pyload/web/app/index.html +++ b/pyload/web/app/index.html @@ -80,29 +80,52 @@                      <a href="http://pyload.org/" target="_blank">The pyLoad Team</a><br>                  </div>              </div> -            <div class="span2"> -                <h2 class="block-title">Powered by</h2> +            <div class="span2 block"> +                <h2 class="block-title"> +                    <a href="http://pyload.org" target="_blank"> +                        Community  <i class="icon-comment"></i> +                    </a> +                </h2>                  <hr> -                Bootstrap <br> +                <a href="http://pyload.org" target="_blank">Homepage</a> · +                <a href="http://board.pyload.org" target="_blank">Board</a> · +                <a href="http://pyload.org/chat" target="_blank">Chat</a>              </div> -            <div class="span2"> -                <h2 class="block-title">pyLoad</h2> +            <div class="span2 block"> +                <h2 class="block-title"> +                    <a href="https://twitter.com/pyload" target="_blank"> +                    Follow us  <i class="icon-twitter"></i> +                    </a> +                </h2>                  <hr> -                dsfdsf <br> +                <a href="https://twitter.com/pyload" target="_blank">Twitter</a> · +                <a href="http://www.youtube.com/user/pyloadTeam" target="_blank">Youtube</a>              </div> -            <div class="span2"> -                <h2 class="block-title">Community</h2> +            <div class="span2 block"> +                <h2 class="block-title"> +                    <a href="https://github.com/pyload" target="_blank"> +                    Development  <i class="icon-github"></i> +                    </a> +                </h2>                  <hr> -                asd <br> +                <a href="https://github.com/pyload" target="_blank">Github</a> · +                <a href="http://docs.pyload.org" target="_blank">Documentation</a>              </div> -            <div class="span2"> -                <h2 class="block-title">Development</h2> +            <div class="span2 block"> +                <h2 class="block-title"> +                    <a href="http://pyload.org/donate" target="_blank"> +                    Donate  <i class="icon-bitcoin"> </i> +                    </a> +                </h2>                  <hr> -                asd <br> +                <a href="http://pyload.org/donate" target="_blank">PayPal</a> · +                <a href="http://blockchain.info/address/1JvcfSKuzk3VENJm9XtqGp2DCTesgokkG2" target="_blank">Bitcoin</a> · +                <a href="https://flattr.com/profile/pyload" target="_blank">Flattr</a>              </div> +          </div>      </div>  </footer> diff --git a/pyload/web/app/scripts/models/Setup.js b/pyload/web/app/scripts/models/Setup.js index 82a2978db..424edf452 100644 --- a/pyload/web/app/scripts/models/Setup.js +++ b/pyload/web/app/scripts/models/Setup.js @@ -4,10 +4,30 @@ define(['jquery', 'backbone', 'underscore', 'app', 'utils/apitypes'],          return Backbone.Model.extend({ +            url: App.apiUrl('setup'),              defaults: {                  lang: 'en', +                system: null, +                deps: null,                  user: null,                  password: null +            }, + +            fetch: function(options) { +                options || (options = {}); +                options.url = App.apiUrl('setup'); +                return Backbone.Model.prototype.fetch.call(this, options); +            }, + +            // will get a 409 on success +            submit: function(options) { +                options || (options = {}); +                options.url = App.apiUrl('setup_done'); +                options.data = { +                    user: this.get('user'), +                    password: this.get('password') +                }; +                return Backbone.Model.prototype.fetch.call(this, options);              }          }); diff --git a/pyload/web/app/scripts/views/linkgrabber/packageView.js b/pyload/web/app/scripts/views/linkgrabber/packageView.js index 95c46e3cc..356d39b4b 100644 --- a/pyload/web/app/scripts/views/linkgrabber/packageView.js +++ b/pyload/web/app/scripts/views/linkgrabber/packageView.js @@ -39,9 +39,19 @@ define(['jquery', 'underscore', 'backbone', 'app', 'hbs!tpl/linkgrabber/package'                  return false;              }, -            renamePackage: function() { +            renamePackage: function(e) { +                e.stopPropagation(); +                  this.ui.name.addClass('edit');                  this.ui.name.find('input').focus(); + +                var self = this; +                $(document).one('click', function() { +                    self.ui.name.removeClass('edit'); +                    self.ui.name.focus(); +                }); + +                return false;              },              saveName: function(e) { diff --git a/pyload/web/app/scripts/views/setup/finishedView.js b/pyload/web/app/scripts/views/setup/finishedView.js new file mode 100644 index 000000000..9f0f8db19 --- /dev/null +++ b/pyload/web/app/scripts/views/setup/finishedView.js @@ -0,0 +1,25 @@ +define(['jquery', 'backbone', 'underscore', 'app', 'hbs!tpl/setup/finished'], +    function($, Backbone, _, App, template) { +        'use strict'; + +        return Backbone.Marionette.ItemView.extend({ + +            name: 'Finished', +            template: template, + +            events: { +                'click .btn-blue': 'confirm' +            }, + +            ui: { +            }, + +            onRender: function() { +            }, + +            confirm: function() { +                this.model.submit(); +            } + +        }); +    });
\ No newline at end of file diff --git a/pyload/web/app/scripts/views/setup/setupView.js b/pyload/web/app/scripts/views/setup/setupView.js index 7636a0bc2..8ab6fba51 100644 --- a/pyload/web/app/scripts/views/setup/setupView.js +++ b/pyload/web/app/scripts/views/setup/setupView.js @@ -1,6 +1,6 @@ -define(['jquery', 'backbone', 'underscore', 'app', 'models/Setup', 'hbs!tpl/setup/layout', 'hbs!tpl/setup/actionbar', -    './welcomeView', './systemView'], -    function($, Backbone, _, App, Setup, template, templateBar, welcomeView, systemView) { +define(['jquery', 'backbone', 'underscore', 'app', 'models/Setup', 'hbs!tpl/setup/layout', 'hbs!tpl/setup/actionbar', 'hbs!tpl/setup/error', +    './welcomeView', './systemView', './userView', './finishedView'], +    function($, Backbone, _, App, Setup, template, templateBar, templateError, welcomeView, systemView, userView, finishedView) {          'use strict';          return Backbone.Marionette.ItemView.extend({ @@ -15,11 +15,14 @@ define(['jquery', 'backbone', 'underscore', 'app', 'models/Setup', 'hbs!tpl/setu              pages: [                  welcomeView, -                systemView +                systemView, +                userView, +                finishedView              ],              page: 0,              view: null, +            error: null,              initialize: function() {                  var self = this; @@ -52,37 +55,66 @@ define(['jquery', 'backbone', 'underscore', 'app', 'models/Setup', 'hbs!tpl/setu                  });                  this.listenTo(this.model, 'page:next', function() { -                    self.openPage(self.page++); +                    self.openPage(self.page + 1);                  });                  this.listenTo(this.model, 'page:prev', function() { -                    self.openPage(self.page--); +                    self.openPage(self.page - 1);                  }); + +                this.listenTo(this.model, 'error', this.onError); +                this.model.fetch();              },              openPage: function(page) {                  console.log('Change page', page);                  // check if number is reasonable -                if (!_.isNumber(page) || !_.isFinite(page)) +                if (!_.isNumber(page) || !_.isFinite(page) || page < 0 || page >= this.pages.length)                      return;                  if (page === this.page)                      return; +                // Render error directly +                if (this.error) { +                    this.onRender(); +                    return; +                } +                  this.page = page; -                this.onRender(); + +                var self = this; +                this.ui.page.fadeOut({complete: function() { +                    self.onRender(); +                }});                  this.model.trigger('page:changed', page);              }, +            onError: function(model, xhr) { +                console.log('Setup error', xhr); +                this.error = xhr; +                this.onRender(); +            }, +              onRender: function() { +                  // close old opened view                  if (this.view)                      this.view.close(); -                // TODO: animation +                // Render error if occurred +                if (this.error) { +                    this.ui.page.html(templateError(this.error)); +                    return; +                } +                  this.view = new this.pages[this.page]({model: this.model});                  this.ui.page.empty(); -                this.ui.page.append(this.view.render().$el); + +                var el = this.view.render().el; +                this.ui.page.append(el); + +                this.ui.page.fadeIn();              }          }); diff --git a/pyload/web/app/scripts/views/setup/systemView.js b/pyload/web/app/scripts/views/setup/systemView.js index 11e50213d..b4c0f7e12 100644 --- a/pyload/web/app/scripts/views/setup/systemView.js +++ b/pyload/web/app/scripts/views/setup/systemView.js @@ -8,12 +8,17 @@ define(['jquery', 'backbone', 'underscore', 'app', 'hbs!tpl/setup/system'],              template: template,              events: { +                'click .btn-blue': 'nextPage'              },              ui: {              },              onRender: function() { +            }, + +            nextPage: function() { +                this.model.trigger('page:next');              }          }); diff --git a/pyload/web/app/scripts/views/setup/userView.js b/pyload/web/app/scripts/views/setup/userView.js new file mode 100644 index 000000000..95eaa0dc2 --- /dev/null +++ b/pyload/web/app/scripts/views/setup/userView.js @@ -0,0 +1,39 @@ +define(['jquery', 'backbone', 'underscore', 'app', 'hbs!tpl/setup/user'], +    function($, Backbone, _, App, template) { +        'use strict'; + +        return Backbone.Marionette.ItemView.extend({ + +            name: 'User', +            template: template, + +            events: { +                'click .btn-blue': 'submit' +            }, + +            ui: { +                username: '#username', +                password: '#password', +                password2: '#password2' +            }, + +            onRender: function() { +            }, + +            submit: function() { +                var pw = this.ui.password.val(); +                var pw2 = this.ui.password2.val(); + +                // TODO more checks and error messages +                if (pw !== pw2) { +                    return; +                } + +                this.model.set('user', this.ui.username.val()); +                this.model.set('password', pw); + +                this.model.trigger('page:next'); +            } + +        }); +    });
\ No newline at end of file diff --git a/pyload/web/app/scripts/views/setup/welcomeView.js b/pyload/web/app/scripts/views/setup/welcomeView.js index 4affc9075..a964e0d42 100644 --- a/pyload/web/app/scripts/views/setup/welcomeView.js +++ b/pyload/web/app/scripts/views/setup/welcomeView.js @@ -8,12 +8,17 @@ define(['jquery', 'backbone', 'underscore', 'app', 'hbs!tpl/setup/welcome'],              template: template,              events: { +                'click .btn-blue': 'nextPage'              },              ui: {              },              onRender: function() { +            }, + +            nextPage: function() { +                this.model.trigger('page:next');              }          }); diff --git a/pyload/web/app/styles/default/main.less b/pyload/web/app/styles/default/main.less index 6bf21e80b..6153b576e 100644 --- a/pyload/web/app/styles/default/main.less +++ b/pyload/web/app/styles/default/main.less @@ -13,10 +13,10 @@  @import "settings";  @import "accounts";  @import "admin"; +@import "setup";  @ResourcePath: "../..";  @DefaultFont: 'Abel', sans-serif;  // Changed dimensions -@header-height: 70px; -@footer-height: 66px;
\ No newline at end of file +@header-height: 70px;;
\ No newline at end of file diff --git a/pyload/web/app/styles/default/setup.less b/pyload/web/app/styles/default/setup.less new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/pyload/web/app/styles/default/setup.less diff --git a/pyload/web/app/styles/default/style.less b/pyload/web/app/styles/default/style.less index da0e68991..ad60e5b59 100644 --- a/pyload/web/app/styles/default/style.less +++ b/pyload/web/app/styles/default/style.less @@ -284,15 +284,4 @@ header { //  background-color: @greyDark;    border-radius: 15px;    -moz-border-radius: 15px;    -webkit-border-radius: 15px; -} - -/* -    Footer -*/ -footer .copyright { -  background-size: 40px 40px; -  background-position: 12px center; -  height: 40px; -  padding-left: 40px; -  padding-top: 10px; -} +}
\ No newline at end of file diff --git a/pyload/web/app/templates/default/setup/error.html b/pyload/web/app/templates/default/setup/error.html new file mode 100644 index 000000000..37ce51283 --- /dev/null +++ b/pyload/web/app/templates/default/setup/error.html @@ -0,0 +1,14 @@ +{{#ifEq status 410}} +    <h2 class="text-warning">{{ _ "Setup timed out" }}</h2> +    <p>{{ _ "Setup was closed due to inactivity. Please restart it to continue configuration." }}</p> +{{else}} +{{#ifEq status 409}} +    <h2 class="text-success">{{ _ "Setup finished" }}</h2> +    <p>{{ _ "Setup was successful. You can restart pyLoad now." }}</p> +{{else}} +    <h2 class="text-error"> +        {{ _ "Setup failed" }} +    </h2> +    <p>{{ _ "Try to restart it or open a bug report." }}</p> +{{/ifEq}} +{{/ifEq}}
\ No newline at end of file diff --git a/pyload/web/app/templates/default/setup/finished.html b/pyload/web/app/templates/default/setup/finished.html new file mode 100644 index 000000000..22a97649b --- /dev/null +++ b/pyload/web/app/templates/default/setup/finished.html @@ -0,0 +1,23 @@ +{{#if user}} + +<h2> +    {{ _ "Nearly Done" }} +</h2> + +<p> +    {{ _ "Please check your settings." }} +</p> + +<p> +    <strong>Username:</strong> {{user}} +</p> + +<button class="btn btn-large btn-blue"> +    {{ _ "Confirm" }} +</button> + +{{else}} + +<h2>{{ _ "Please add a user first." }}</h2> + +{{/if}} diff --git a/pyload/web/app/templates/default/setup/layout.html b/pyload/web/app/templates/default/setup/layout.html index 7b75e53b1..2e986173a 100644 --- a/pyload/web/app/templates/default/setup/layout.html +++ b/pyload/web/app/templates/default/setup/layout.html @@ -3,5 +3,8 @@          {{ _ "Setup" }}      </h1>  </div> -<div class="span8 setup-page"> +<div class="span8"> +    <div class="hero-unit setup-page"> + +    </div>  </div>
\ No newline at end of file diff --git a/pyload/web/app/templates/default/setup/system.html b/pyload/web/app/templates/default/setup/system.html index 84a217b19..0c5023669 100644 --- a/pyload/web/app/templates/default/setup/system.html +++ b/pyload/web/app/templates/default/setup/system.html @@ -1,5 +1,56 @@ -<h1>{{ _ "System" }} </h1> +<h3>{{ _ "System" }} </h3> -<h2>{{_ "Dependencies" }}</h2> +<dl class="dl-horizontal"> +    {{#each system}} +        <dt>{{ @key }}</dt> +        <dd>{{ this }}</dd> +    {{/each}} +</dl> -<h2>{{ _ "Optional" }}</h2>
\ No newline at end of file +<h3>{{_ "Dependencies" }}</h3> +<dl class="dl-horizontal"> +    {{#each deps.core}} +    <dt>{{ name }}</dt> +    <dd> +        {{#if avail}} +            <span class="text-success"> +                <i class="icon-ok"></i> +                {{#if v}} +                 ({{v}}) +                {{/if}} +            </span> +        {{else}} +            <span class="text-error"> +                <i class="icon-remove"></i> +            </span> +        {{/if}} +    </dd> +    {{/each}} +</dl> + + +<h4>{{ _ "Optional" }}</h4> +<dl class="dl-horizontal"> +    {{#each deps.opt}} +    <dt>{{ name }}</dt> +    <dd> +        {{#if avail}} +            <span class="text-success"> +                {{ _ "available" }} +                {{#if v}} +                 ({{v}}) +                {{/if}} +            </span> +        {{else}} +            <span class="text-error"> +                {{ _ "not available" }} +            </span> +        {{/if}} +    </dd> +    {{/each}} +</dl> + + +<button class="btn btn-blue"> +    {{ _ "Next" }} +</button>
\ No newline at end of file diff --git a/pyload/web/app/templates/default/setup/user.html b/pyload/web/app/templates/default/setup/user.html new file mode 100644 index 000000000..fe3f2de71 --- /dev/null +++ b/pyload/web/app/templates/default/setup/user.html @@ -0,0 +1,34 @@ +<form class="form-horizontal"> +    <div class="control-group"> +        <label class="control-label"> +            Username +        </label> + +        <div class="controls"> +            <input type="text" id="username" placeholder="User"> +        </div> +    </div> +    <div class="control-group"> +        <label class="control-label"> +            Password +        </label> + +        <div class="controls"> +            <input type="password" id="password"> +        </div> +    </div> +    <div class="control-group"> +        <label class="control-label"> +            Password (again) +        </label> + +        <div class="controls"> +            <input type="password" id="password2"> +        </div> +    </div> +    <div class="control-group"> +        <div class="controls"> +                <a class="btn btn-blue">Submit</a> +        </div> +    </div> +</form>
\ No newline at end of file diff --git a/pyload/web/app/templates/default/setup/welcome.html b/pyload/web/app/templates/default/setup/welcome.html index f5c5af4d7..5a4f74d9f 100644 --- a/pyload/web/app/templates/default/setup/welcome.html +++ b/pyload/web/app/templates/default/setup/welcome.html @@ -1,16 +1,14 @@ -<div class="hero-unit"> -    <h1>{{ _ "Welcome!" }}</h1> +<h1>{{ _ "Welcome!" }}</h1> -    <p>{{ _ "pyLoad is running and ready for configuration." }}</p> +<p>{{ _ "pyLoad is running and ready for configuration." }}</p> -    <p> -        {{ _ "Select your language:" }} -        <select> -            <option>en</option> -        </select> -    </p> +<p> +    {{ _ "Select your language:" }} +    <select> +        <option>en</option> +    </select> +</p> -    <button class="btn btn-large btn-blue"> -       {{ _ "Start configuration" }} -    </button> -</div>
\ No newline at end of file +<button class="btn btn-large btn-blue"> +    {{ _ "Start configuration" }} +</button>
\ No newline at end of file diff --git a/pyload/web/bower.json b/pyload/web/bower.json index b0176a891..4da3634a0 100644 --- a/pyload/web/bower.json +++ b/pyload/web/bower.json @@ -11,7 +11,7 @@          "jquery.cookie": "~1.3.1",          "jquery.animate-enhanced": "*",          "flot": "~0.8.1", -        "underscore": "~1.4.4", +        "underscore": "~1.5.1",          "backbone": "~1.0.0",          "backbone.marionette": "~1.1.0",          "handlebars.js": "1.0.0-rc.3", diff --git a/pyload/web/middlewares.py b/pyload/web/middlewares.py index 074681b8f..af355bf11 100644 --- a/pyload/web/middlewares.py +++ b/pyload/web/middlewares.py @@ -1,17 +1,6 @@  #!/usr/bin/env python  # -*- coding: utf-8 -*- -# gzip is optional on some platform -try: -    import gzip -except ImportError: -    gzip = None - -try: -    from cStringIO import StringIO -except ImportError: -    from StringIO import StringIO -  class StripPathMiddleware(object):      def __init__(self, app):          self.app = app @@ -31,105 +20,3 @@ class PrefixMiddleware(object):          if path.startswith(self.prefix):              e['PATH_INFO'] = path.replace(self.prefix, "", 1)          return self.app(e, h) - -# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) -# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php - -# WSGI middleware -# Gzip-encodes the response. - -# TODO: not in use anymore, because of pre-gzipped resources -class GZipMiddleWare(object): - -    def __init__(self, application, compress_level=6): -        self.application = application -        self.compress_level = int(compress_level) - -    def __call__(self, environ, start_response): -        if 'gzip' not in environ.get('HTTP_ACCEPT_ENCODING', ''): -            # nothing for us to do, so this middleware will -            # be a no-op: -            return self.application(environ, start_response) -        response = GzipResponse(start_response, self.compress_level) -        app_iter = self.application(environ, -                                    response.gzip_start_response) -        if app_iter is not None: -            response.finish_response(app_iter) - -        return response.write() - -def header_value(headers, key): -    for header, value in headers: -        if key.lower() == header.lower(): -            return value - -def update_header(headers, key, value): -    remove_header(headers, key) -    headers.append((key, value)) - -def remove_header(headers, key): -    for header, value in headers: -        if key.lower() == header.lower(): -            headers.remove((header, value)) -            break - -class GzipResponse(object): - -    def __init__(self, start_response, compress_level): -        self.start_response = start_response -        self.compress_level = compress_level -        self.buffer = StringIO() -        self.compressible = False -        self.content_length = None -        self.headers = () - -    def gzip_start_response(self, status, headers, exc_info=None): -        self.headers = headers -        ct = header_value(headers,'content-type') -        ce = header_value(headers,'content-encoding') -        cl = header_value(headers, 'content-length') - -        # don't compress on unknown size, it may be too huge -        cl = int(cl) if cl else 0 - -        if ce: -            self.compressible = False -        elif gzip is not None and ct and (ct.startswith('text/') or ct.startswith('application/')) \ -            and 'zip' not in ct and 200 < cl < 1024*1024: -            self.compressible = True -            headers.append(('content-encoding', 'gzip')) -            headers.append(('vary', 'Accept-Encoding')) - -        remove_header(headers, 'content-length') -        self.headers = headers -        self.status = status -        return self.buffer.write - -    def write(self): -        out = self.buffer -        out.seek(0) -        s = out.getvalue() -        out.close() -        return [s] - -    def finish_response(self, app_iter): -        if self.compressible: -            output = gzip.GzipFile(mode='wb', compresslevel=self.compress_level, -                fileobj=self.buffer) -        else: -            output = self.buffer -        try: -            for s in app_iter: -                output.write(s) -            if self.compressible: -                output.close() -        finally: -            if hasattr(app_iter, 'close'): -                try: -                    app_iter.close() -                except : -                    pass - -        content_length = self.buffer.tell() -        update_header(self.headers, "Content-Length" , str(content_length)) -        self.start_response(self.status, self.headers)
\ No newline at end of file diff --git a/pyload/web/pyload_app.py b/pyload/web/pyload_app.py index 1ec7cf4c9..1c89e2ada 100644 --- a/pyload/web/pyload_app.py +++ b/pyload/web/pyload_app.py @@ -70,7 +70,11 @@ def index():      # set variable depending on setup mode      setup = 'false' if SETUP is None else 'true'      ws = PYLOAD.getWSAddress() if PYLOAD else False -    web = PYLOAD.getConfigValue('webinterface', 'port') if PYLOAD else False +    web = None +    if PYLOAD: +        web = PYLOAD.getConfigValue('webinterface', 'port') +    elif SETUP: +        web = SETUP.config['webinterface']['port']      # Render variables into the html page      if resp.status_code == 200: diff --git a/pyload/web/setup_app.py b/pyload/web/setup_app.py index 5163f9cc6..939fcb600 100644 --- a/pyload/web/setup_app.py +++ b/pyload/web/setup_app.py @@ -3,26 +3,71 @@  from time import time +from pyload.utils import json_dumps +  from bottle import route, request, response, HTTPError, redirect  from webinterface import PROJECT_DIR, SETUP  from utils import add_json_header +# returns http error +def error(code, msg): +    return HTTPError(code, json_dumps(msg), **dict(response.headers)) + +  def setup_required(func):      def _view(*args, **kwargs): +        global timestamp +          # setup needs to be running          if SETUP is None: -            redirect("/nopermission") +            return error(404, "Not Found") + +        # setup finished +        if timestamp == 0: +            return error(409, "Done") + +        # setup timed out due to inactivity +        if timestamp + TIMEOUT * 60 < time(): +            return error(410, "Timeout") + +        timestamp = time()          return func(*args, **kwargs) +      return _view  # setup will close after inactivity  TIMEOUT = 15  timestamp = time() +  @route("/setup")  @setup_required  def setup(): -    pass # TODO +    add_json_header(response) + +    return json_dumps({ +        "system": SETUP.check_system(), +        "deps": SETUP.check_deps() +    }) + + +@route("/setup_done") +@setup_required +def setup_done(): +    global timestamp +    add_json_header(response) + +    SETUP.addUser( +        request.params['user'], +        request.params['password'] +    ) + +    SETUP.save() + +    # mark setup as finished +    timestamp = 0 + +    return error(409, "Done") diff --git a/pyload/web/utils.py b/pyload/web/utils.py index e94089185..7e8ee3f13 100644 --- a/pyload/web/utils.py +++ b/pyload/web/utils.py @@ -4,14 +4,21 @@  import re  from bottle import request, HTTPError, redirect +try: +    import zlib +except ImportError: +    zlib = None +  from webinterface import PYLOAD, SETUP +  def add_json_header(r):      r.headers.replace("Content-type", "application/json")      r.headers.append("Cache-Control", "no-cache, must-revalidate")      r.headers.append("Access-Control-Allow-Origin", request.get_header('Origin', '*'))      r.headers.append("Access-Control-Allow-Credentials", "true") +  def set_session(request, user):      s = request.environ.get('beaker.session')      s["uid"] = user.uid @@ -58,15 +65,14 @@ def is_mobile():          return True      return False -def select_language(langs): +def select_language(langs):      accept = request.headers.get('Accept-Language', '')      # TODO      return langs[0] -  def login_required(perm=None):      def _dec(func):          def _view(*args, **kwargs): | 
