1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-08-01 15:23:05 +00:00

Implement Sysinfo

This commit is contained in:
Daniel Pan 2016-03-16 16:21:53 +08:00 committed by lian
parent 899f5241d4
commit bcc4e42142
9 changed files with 240 additions and 6 deletions

View File

@ -820,6 +820,16 @@ textarea:-moz-placeholder {/* for FF */
margin:0;
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 {
width:320px;

View 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)

View File

@ -46,3 +46,56 @@
{% endif %}
</ul>
</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>

View File

@ -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_update import FileUpdate
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:
#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})/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/admin/sysinfo/$', SysInfo.as_view(), name='api-v2.1-sysinfo'),
(r'^avatar/', include('seahub.avatar.urls')),
(r'^notification/', include('seahub.notifications.urls')),

View File

@ -1026,11 +1026,11 @@ if HAS_OFFICE_CONVERTER:
def cluster_delegate(delegate_func):
'''usage:
@cluster_delegate(funcA)
def func(*args):
...non-cluster logic goes here...
- In non-cluster mode, this decorator effectively does nothing.
- In cluster mode, if this node is not the office convert node,
funcA is called instead of the decorated function itself
@ -1261,6 +1261,10 @@ def do_urlopen(url, data=None, headers=None):
return ret
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:
return True
else:

View File

@ -154,6 +154,8 @@ define([
case 'search_user': return siteRoot + 'api2/search-user/';
case 'user_profile': return siteRoot + 'profile/' + options.username + '/';
case 'space_and_traffic': return siteRoot + 'ajax/space_and_traffic/';
// sysadmin
case 'sysinfo': return siteRoot + 'api/v2.1/admin/sysinfo/';
}
},

View 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;
});

View File

@ -41,6 +41,7 @@ define([
showDashboard: function() {
this.switchCurrentView(this.dashboardView);
this.sideNavView.setCurTab('dashboard');
this.dashboardView.show();
}
});

View File

@ -2,23 +2,43 @@ define([
'jquery',
'underscore',
'backbone',
'common'
], function($, _, Backbone, Common) {
'common',
'sysadmin-app/models/SysInfo'
], function($, _, Backbone, Common, SysInfo) {
'use strict';
var DashboardView = Backbone.View.extend({
tagName: 'div',
template: _.template($("#sysinfo-tmpl").html()),
initialize: function() {
this.sysinfo = new SysInfo();
},
events: {
},
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() {
@ -26,7 +46,15 @@ define([
},
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;
}
});