mirror of
https://github.com/haiwen/seahub.git
synced 2025-08-14 13:13:22 +00:00
Implement Sysinfo
This commit is contained in:
parent
899f5241d4
commit
bcc4e42142
@ -820,6 +820,16 @@ textarea:-moz-placeholder {/* for FF */
|
|||||||
margin:0;
|
margin:0;
|
||||||
color:#000;
|
color:#000;
|
||||||
}
|
}
|
||||||
|
/***** header *****/
|
||||||
|
.header-bar {
|
||||||
|
padding:9px 10px;
|
||||||
|
background:#f2f2f2;
|
||||||
|
margin-bottom:.5em;
|
||||||
|
border-radius:2px;
|
||||||
|
padding-bottom:0;
|
||||||
|
height:39px;
|
||||||
|
overflow:hidden;
|
||||||
|
}
|
||||||
/**** narrow-panel ****/
|
/**** narrow-panel ****/
|
||||||
.narrow-panel {
|
.narrow-panel {
|
||||||
width:320px;
|
width:320px;
|
||||||
|
117
seahub/api2/endpoints/admin/sysinfo.py
Normal file
117
seahub/api2/endpoints/admin/sysinfo.py
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.utils.dateformat import DateFormat
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
|
from django.template.defaultfilters import filesizeformat
|
||||||
|
|
||||||
|
from rest_framework.authentication import SessionAuthentication
|
||||||
|
from rest_framework.permissions import IsAuthenticated, IsAdminUser
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from rest_framework.views import APIView
|
||||||
|
from rest_framework import status
|
||||||
|
|
||||||
|
from seaserv import seafile_api, ccnet_api
|
||||||
|
from pysearpc import SearpcError
|
||||||
|
|
||||||
|
from seahub.utils.rpc import mute_seafile_api
|
||||||
|
from seahub.utils import is_pro_version
|
||||||
|
from seahub.utils.licenseparse import parse_license
|
||||||
|
|
||||||
|
from seahub.api2.utils import api_error
|
||||||
|
from seahub.api2.authentication import TokenAuthentication
|
||||||
|
from seahub.api2.throttling import UserRateThrottle
|
||||||
|
|
||||||
|
import seahub.settings
|
||||||
|
try:
|
||||||
|
from seahub.settings import MULTI_TENANCY
|
||||||
|
except ImportError:
|
||||||
|
MULTI_TENANCY = False
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class SysInfo(APIView):
|
||||||
|
"""Show system info.
|
||||||
|
"""
|
||||||
|
authentication_classes = (TokenAuthentication, SessionAuthentication)
|
||||||
|
permission_classes = (IsAdminUser,)
|
||||||
|
|
||||||
|
def get(self, request, format=None):
|
||||||
|
# count repos
|
||||||
|
repos_count = mute_seafile_api.count_repos()
|
||||||
|
|
||||||
|
# count groups
|
||||||
|
try:
|
||||||
|
groups_count = len(ccnet_api.get_all_groups(-1, -1))
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(e)
|
||||||
|
groups_count = 0
|
||||||
|
|
||||||
|
# count orgs
|
||||||
|
if MULTI_TENANCY:
|
||||||
|
multi_tenacy_enabled = True
|
||||||
|
try:
|
||||||
|
org_count = ccnet_api.count_orgs()
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(e)
|
||||||
|
org_count = 0
|
||||||
|
else:
|
||||||
|
multi_tenacy_enabled = False
|
||||||
|
org_count = 0
|
||||||
|
|
||||||
|
# count users
|
||||||
|
try:
|
||||||
|
active_db_users = ccnet_api.count_emailusers('DB')
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(e)
|
||||||
|
active_db_users = 0
|
||||||
|
|
||||||
|
try:
|
||||||
|
active_ldap_users = ccnet_api.count_emailusers('LDAP')
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(e)
|
||||||
|
active_ldap_users = 0
|
||||||
|
|
||||||
|
try:
|
||||||
|
inactive_db_users = ccnet_api.count_inactive_emailusers('DB')
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(e)
|
||||||
|
inactive_db_users = 0
|
||||||
|
|
||||||
|
try:
|
||||||
|
inactive_ldap_users = ccnet_api.count_inactive_emailusers('LDAP')
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(e)
|
||||||
|
inactive_ldap_users = 0
|
||||||
|
|
||||||
|
active_users = active_db_users + active_ldap_users if active_ldap_users > 0 \
|
||||||
|
else active_db_users
|
||||||
|
|
||||||
|
inactive_users = inactive_db_users + inactive_ldap_users if inactive_ldap_users > 0 \
|
||||||
|
else inactive_db_users
|
||||||
|
|
||||||
|
is_pro = is_pro_version()
|
||||||
|
if is_pro:
|
||||||
|
license_file = os.path.join(seahub.settings.PROJECT_ROOT, '../../seafile-license.txt')
|
||||||
|
license_dict = parse_license(license_file)
|
||||||
|
else:
|
||||||
|
license_dict = {}
|
||||||
|
|
||||||
|
if license_dict:
|
||||||
|
with_license = True
|
||||||
|
else:
|
||||||
|
with_license = False
|
||||||
|
|
||||||
|
info = {
|
||||||
|
'users_count': active_users + inactive_users,
|
||||||
|
'active_users_count': active_users,
|
||||||
|
'repos_count': repos_count,
|
||||||
|
'groups_count': groups_count,
|
||||||
|
'org_count': org_count,
|
||||||
|
'multi_tenancy_enabled': multi_tenacy_enabled,
|
||||||
|
'is_pro': is_pro,
|
||||||
|
'with_license': with_license,
|
||||||
|
'license': license_dict
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response(info)
|
@ -46,3 +46,56 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<script type="text/template" id="sysinfo-tmpl">
|
||||||
|
<div class="header-bar">
|
||||||
|
<h3 class="">{% trans "Info" %}</h3>
|
||||||
|
</div>
|
||||||
|
<dl>
|
||||||
|
<dt>{% trans "System Info" %}</dt>
|
||||||
|
<dd><% if (is_pro) { %>
|
||||||
|
{% trans "Professional Edition" %}
|
||||||
|
<% if (with_license) { %>
|
||||||
|
{% trans "expires on" %} <%- license.Expiration %>
|
||||||
|
<% } %>
|
||||||
|
<% } else { %>
|
||||||
|
{% trans "Community Edition" %}
|
||||||
|
<a href="http://manual.seafile.com/deploy_pro/migrate_from_seafile_community_server.html" target="_blank">{% trans "Upgrade to Pro Edition" %}</a>
|
||||||
|
<% } %>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>{% trans "Libraries" %}</dt>
|
||||||
|
<dd><%- repos_count %></dd>
|
||||||
|
|
||||||
|
<% if (is_pro) { %>
|
||||||
|
<dt>{% trans "Active Users" %} / {% trans "Total Users" %} / {% trans "Limits" %}</dt>
|
||||||
|
<dd>
|
||||||
|
<%- active_users_count %>
|
||||||
|
/
|
||||||
|
<%- users_count %>
|
||||||
|
/
|
||||||
|
<% if (with_license) { %>
|
||||||
|
<%- license.MaxUsers %>
|
||||||
|
<% } else { %>
|
||||||
|
--
|
||||||
|
<% } %>
|
||||||
|
</dd>
|
||||||
|
<% } else { %>
|
||||||
|
<dt>{% trans "Active Users" %} / {% trans "Total Users" %}</dt>
|
||||||
|
<dd>
|
||||||
|
<%- active_users_count %>
|
||||||
|
/
|
||||||
|
<%- users_count %>
|
||||||
|
</dd>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
|
<dt>{% trans "Groups" %}</dt>
|
||||||
|
<dd><%- groups_count %></dd>
|
||||||
|
|
||||||
|
<% if (multi_tenancy_enabled) { %>
|
||||||
|
<dt>{% trans "Organizations" %}</dt>
|
||||||
|
<dd><%- org_count %></dd>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
|
</dl>
|
||||||
|
</script>
|
||||||
|
@ -28,6 +28,7 @@ from seahub.api2.endpoints.admin.login import Login
|
|||||||
from seahub.api2.endpoints.admin.file_audit import FileAudit
|
from seahub.api2.endpoints.admin.file_audit import FileAudit
|
||||||
from seahub.api2.endpoints.admin.file_update import FileUpdate
|
from seahub.api2.endpoints.admin.file_update import FileUpdate
|
||||||
from seahub.api2.endpoints.admin.perm_audit import PermAudit
|
from seahub.api2.endpoints.admin.perm_audit import PermAudit
|
||||||
|
from seahub.api2.endpoints.admin.sysinfo import SysInfo
|
||||||
|
|
||||||
# Uncomment the next two lines to enable the admin:
|
# Uncomment the next two lines to enable the admin:
|
||||||
#from django.contrib import admin
|
#from django.contrib import admin
|
||||||
@ -189,6 +190,7 @@ urlpatterns = patterns(
|
|||||||
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9-a-f]{36})/file/$', FileView.as_view(), name='api-v2.1-file-view'),
|
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9-a-f]{36})/file/$', FileView.as_view(), name='api-v2.1-file-view'),
|
||||||
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9-a-f]{36})/dir/$', DirView.as_view(), name='api-v2.1-dir-view'),
|
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9-a-f]{36})/dir/$', DirView.as_view(), name='api-v2.1-dir-view'),
|
||||||
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/set-password/$', RepoSetPassword.as_view(), name="api-v2.1-repo-set-password"),
|
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/set-password/$', RepoSetPassword.as_view(), name="api-v2.1-repo-set-password"),
|
||||||
|
url(r'^api/v2.1/admin/sysinfo/$', SysInfo.as_view(), name='api-v2.1-sysinfo'),
|
||||||
|
|
||||||
(r'^avatar/', include('seahub.avatar.urls')),
|
(r'^avatar/', include('seahub.avatar.urls')),
|
||||||
(r'^notification/', include('seahub.notifications.urls')),
|
(r'^notification/', include('seahub.notifications.urls')),
|
||||||
|
@ -1026,11 +1026,11 @@ if HAS_OFFICE_CONVERTER:
|
|||||||
|
|
||||||
def cluster_delegate(delegate_func):
|
def cluster_delegate(delegate_func):
|
||||||
'''usage:
|
'''usage:
|
||||||
|
|
||||||
@cluster_delegate(funcA)
|
@cluster_delegate(funcA)
|
||||||
def func(*args):
|
def func(*args):
|
||||||
...non-cluster logic goes here...
|
...non-cluster logic goes here...
|
||||||
|
|
||||||
- In non-cluster mode, this decorator effectively does nothing.
|
- In non-cluster mode, this decorator effectively does nothing.
|
||||||
- In cluster mode, if this node is not the office convert node,
|
- In cluster mode, if this node is not the office convert node,
|
||||||
funcA is called instead of the decorated function itself
|
funcA is called instead of the decorated function itself
|
||||||
@ -1261,6 +1261,10 @@ def do_urlopen(url, data=None, headers=None):
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
def is_pro_version():
|
def is_pro_version():
|
||||||
|
if seahub.settings.DEBUG:
|
||||||
|
if hasattr(seahub.settings, 'IS_PRO_VERSION') \
|
||||||
|
and seahub.settings.IS_PRO_VERSION:
|
||||||
|
return True
|
||||||
if EVENTS_CONFIG_FILE:
|
if EVENTS_CONFIG_FILE:
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
|
@ -154,6 +154,8 @@ define([
|
|||||||
case 'search_user': return siteRoot + 'api2/search-user/';
|
case 'search_user': return siteRoot + 'api2/search-user/';
|
||||||
case 'user_profile': return siteRoot + 'profile/' + options.username + '/';
|
case 'user_profile': return siteRoot + 'profile/' + options.username + '/';
|
||||||
case 'space_and_traffic': return siteRoot + 'ajax/space_and_traffic/';
|
case 'space_and_traffic': return siteRoot + 'ajax/space_and_traffic/';
|
||||||
|
// sysadmin
|
||||||
|
case 'sysinfo': return siteRoot + 'api/v2.1/admin/sysinfo/';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
17
static/scripts/sysadmin-app/models/sysinfo.js
Normal file
17
static/scripts/sysadmin-app/models/sysinfo.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
define([
|
||||||
|
'underscore',
|
||||||
|
'backbone',
|
||||||
|
'common'
|
||||||
|
], function(_, Backbone, Common) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var SysInfo = Backbone.Model.extend({
|
||||||
|
|
||||||
|
url: function () {
|
||||||
|
return Common.getUrl({name: 'sysinfo'});
|
||||||
|
},
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
return SysInfo;
|
||||||
|
});
|
@ -41,6 +41,7 @@ define([
|
|||||||
showDashboard: function() {
|
showDashboard: function() {
|
||||||
this.switchCurrentView(this.dashboardView);
|
this.switchCurrentView(this.dashboardView);
|
||||||
this.sideNavView.setCurTab('dashboard');
|
this.sideNavView.setCurTab('dashboard');
|
||||||
|
this.dashboardView.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -2,23 +2,43 @@ define([
|
|||||||
'jquery',
|
'jquery',
|
||||||
'underscore',
|
'underscore',
|
||||||
'backbone',
|
'backbone',
|
||||||
'common'
|
'common',
|
||||||
], function($, _, Backbone, Common) {
|
'sysadmin-app/models/SysInfo'
|
||||||
|
], function($, _, Backbone, Common, SysInfo) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var DashboardView = Backbone.View.extend({
|
var DashboardView = Backbone.View.extend({
|
||||||
|
|
||||||
tagName: 'div',
|
tagName: 'div',
|
||||||
|
template: _.template($("#sysinfo-tmpl").html()),
|
||||||
|
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
|
this.sysinfo = new SysInfo();
|
||||||
},
|
},
|
||||||
|
|
||||||
events: {
|
events: {
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
|
var _this = this;
|
||||||
|
this.sysinfo.fetch({
|
||||||
|
success: function(model, response, options) {
|
||||||
|
_this._showContent();
|
||||||
|
},
|
||||||
|
error: function(model, response, options) {
|
||||||
|
var err_msg;
|
||||||
|
if (response.responseText) {
|
||||||
|
if (response['status'] == 401 || response['status'] == 403) {
|
||||||
|
err_msg = gettext("Permission error");
|
||||||
|
} else {
|
||||||
|
err_msg = $.parseJSON(response.responseText).error_msg;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err_msg = gettext("Failed. Please check the network.");
|
||||||
|
}
|
||||||
|
Common.feedback(err_msg, 'error');
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
hide: function() {
|
hide: function() {
|
||||||
@ -26,7 +46,15 @@ define([
|
|||||||
},
|
},
|
||||||
|
|
||||||
show: function() {
|
show: function() {
|
||||||
|
this.render();
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
_showContent: function() {
|
||||||
|
console.log(this.sysinfo.toJSON());
|
||||||
|
this.$el.html(this.template(this.sysinfo.toJSON()));
|
||||||
|
$("#right-panel").html(this.$el);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user