1
0
mirror of https://github.com/dkmstr/openuds.git synced 2024-12-24 21:34:41 +03:00

Merged from 2.1

This commit is contained in:
Adolfo Gómez García 2017-01-23 11:54:35 +01:00
commit 3f110fb6c6
11 changed files with 302 additions and 37 deletions

View File

@ -46,6 +46,8 @@ from uds.models import Authenticator, User, Group
from uds.core.auths.User import User as aUser
from uds.core.managers import cryptoManager
from uds.REST import RequestError
from uds.core.ui.images import DEFAULT_THUMB_BASE64
from .user_services import AssignedService
from uds.REST.model import DetailHandler
@ -55,9 +57,16 @@ logger = logging.getLogger(__name__)
# Details of /auth
def getPoolsForGroups(groups):
for g in groups:
for servicePool in g.deployedServices.all():
yield servicePool
class Users(DetailHandler):
custom_methods = ['servicesPools', 'userServices']
@staticmethod
def uuid_to_id(iterator):
for v in iterator:
@ -166,9 +175,40 @@ class Users(DetailHandler):
return 'deleted'
def servicesPools(self, parent, item):
uuid = processUuid(item)
user = parent.users.get(uuid=processUuid(uuid))
res = []
for i in getPoolsForGroups(user.groups.all()):
res.append({
'id': i.uuid,
'name': i.name,
'thumb': i.image.thumb64 if i.image is not None else DEFAULT_THUMB_BASE64,
'user_services_count': i.userServices.count(),
'state': _('With errors') if i.isRestrained() else _('Ok'),
})
return res
def userServices(self, parent, item):
uuid = processUuid(item)
user = parent.users.get(uuid=processUuid(uuid))
res = []
for i in user.userServices.all():
if i.state == State.USABLE:
v = AssignedService.itemToDict(i)
v['pool'] = i.deployed_service.name
v['pool_id'] = i.deployed_service.uuid
res.append(v)
return res
class Groups(DetailHandler):
custom_methods = ['servicesPools']
def getItems(self, parent, item):
try:
multi = False
@ -287,3 +327,18 @@ class Groups(DetailHandler):
self.invalidItemException()
return 'deleted'
def servicesPools(self, parent, item):
uuid = processUuid(item)
group = parent.groups.get(uuid=processUuid(uuid))
res = []
for i in getPoolsForGroups((group,)):
res.append({
'id': i.uuid,
'name': i.name,
'thumb': i.image.thumb64 if i.image is not None else DEFAULT_THUMB_BASE64,
'user_services_count': i.userServices.count(),
'state': _('With errors') if i.isRestrained() else _('Ok'),
})
return res

View File

@ -63,7 +63,7 @@ from datetime import datetime, timedelta
import logging
import pickle
__updated__ = '2017-01-20'
__updated__ = '2017-01-23'
logger = logging.getLogger(__name__)

View File

@ -44,8 +44,8 @@ class WinDomainOsManager(WindowsOsManager):
if values is not None:
if values['domain'] == '':
raise osmanagers.OSManager.ValidationException(_('Must provide a domain!'))
if values['domain'].find('.') == -1:
raise osmanagers.OSManager.ValidationException(_('Must provide domain in FQDN'))
# if values['domain'].find('.') == -1:
# raise osmanagers.OSManager.ValidationException(_('Must provide domain in FQDN'))
if values['account'] == '':
raise osmanagers.OSManager.ValidationException(_('Must provide an account to add machines to domain!'))
if values['account'].find('\\') != -1:

View File

@ -1,7 +1,7 @@
# jshint strict: true
# jshint strict: true
((api, $, undefined_) ->
"use strict"
api.tools =
api.tools =
base64: (s) ->
window.btoa unescape(encodeURIComponent(s))
input2timeStamp: (inputDate, inputTime) ->
@ -36,7 +36,7 @@
capitalize: (str) ->
str = str.toLowerCase()
return str.substr(0,1).toUpperCase() + str.substr(1)
return str
isEmpty: (obj) ->
@ -110,7 +110,7 @@ localizedStrftime = (locale) ->
# - timezone [number] timezone offset in minutes from GMT
_strftime = (fmt, d, locale, options) ->
options = options or {}
# d and locale are optional so check if d is really the locale
if d and not quacksLikeDate(d)
locale = d
@ -118,13 +118,13 @@ _strftime = (fmt, d, locale, options) ->
d = d or new Date()
locale = locale or DefaultLocale
locale.formats = locale.formats or {}
# Hang on to this Unix timestamp because we might mess with it directly
# below.
timestamp = d.getTime()
d = dateToUTC(d) if options.utc or typeof options.timezone is "number"
d = new Date(d.getTime() + (options.timezone * 60000)) if typeof options.timezone is "number"
# Most of the specifiers supported by C's strftime, and some from Ruby.
# Some other syntax extensions from Ruby are supported: %-, %_, and %0
# to pad with nothing, space, or zero (respectively).
@ -133,20 +133,20 @@ _strftime = (fmt, d, locale, options) ->
padding = null
if c.length is 2
mod = c[0]
# omit padding
if mod is "-"
padding = ""
# pad with space
else if mod is "_"
padding = " "
# pad with zero
else if mod is "0"
padding = "0"
else
# unrecognized, return the format
return _
c = c[1]
@ -256,17 +256,17 @@ quacksLikeDate = (x) ->
# Default padding is '0' and default length is 2, both are optional.
pad = (n, padding, length) ->
# pad(n, <length>)
if typeof padding is "number"
length = padding
padding = "0"
# Defaults handle pad(n) and pad(n, <padding>)
padding ?= "0"
length ?= 2
s = String(n)
# padding may be an empty string, don't loop forever if it is
s = padding + s while s.length < length if padding
s
@ -295,7 +295,7 @@ ordinal = (n) ->
# Pilfered & ported from Ruby's strftime implementation.
weekNumber = (d, firstWeekday) ->
firstWeekday = firstWeekday or "sunday"
# This works by shifting the weekday back by one day if we
# are treating Monday as the first day of the week.
wday = d.getDay()

View File

@ -174,8 +174,10 @@ gui.authenticators.link = (event) ->
id = selected[0].id
type = gui.authenticators.types[selected[0].type]
gui.doLog "Type", type
user = new GuiElement(api.authenticators.detail(id, "users", { permission: selected[0].permission }), "users")
group = new GuiElement(api.authenticators.detail(id, "groups", { permission: selected[0].permission }), "groups")
userAPI = api.authenticators.detail(id, "users", { permission: selected[0].permission })
user = new GuiElement(userAPI, "users")
groupAPI = api.authenticators.detail(id, "groups", { permission: selected[0].permission })
group = new GuiElement(groupAPI, "groups")
grpTable = group.table(
icon: 'groups'
container: "groups-placeholder"
@ -292,6 +294,127 @@ gui.authenticators.link = (event) ->
# New button will only be shown on authenticators that can create new users
usrButtons = [
"edit"
{
text: gui.tools.iconAndText( 'fa-info', gettext('Information') )
css: "disabled"
disabled: true
click: (vals, value, btn, tbl, refreshFnc) ->
if vals.length > 1
return
val = vals[0]
userAPI.invoke val.id + "/servicesPools", (pools) ->
userAPI.invoke val.id + "/userServices", (userServices) ->
user.rest.item val.id, (item) ->
group.rest.overview (groups) -> # Get groups
gui.doLog "Pools", pools
api.templates.get "user-info", (tmpl) ->
content = api.templates.evaluate(tmpl,
id: 'information',
groups_all: groups
groups: item.groups
pools: pools,
userServices: userServices,
goClass: 'goLink'
)
modalId = gui.launchModal(gettext('User information'), content,
actionButton: " "
)
$('#information-groups-table').DataTable(
colReorder: true
stateSave: true
paging: true
info: false
autoWidth: false
lengthChange: false
pageLength: 10
columnDefs: [
{ 'width': '100%', 'targets': 0 },
]
ordering: true
order: [[ 0, 'asc' ]]
dom: '<>fr<"uds-table"t>ip'
language: gui.config.dataTablesLanguage
)
$('#information-pools-table').DataTable(
colReorder: true
stateSave: true
paging: true
info: false
autoWidth: false
lengthChange: false
pageLength: 10
columnDefs: [
{ 'width': '50%', 'targets': 0 },
{ 'width': '120px', 'targets': 1 },
{ 'width': '40px', 'targets': 2 },
{ 'width': '160px', 'targets': 3 },
]
ordering: true
order: [[ 1, 'asc' ]]
dom: '<>fr<"uds-table"t>ip'
language: gui.config.dataTablesLanguage
)
$('#information-userservices-table').DataTable(
colReorder: true
stateSave: true
paging: true
info: false
autoWidth: false
lengthChange: false
pageLength: 10
columnDefs: [
{ 'width': '25%', 'targets': 0 },
{ 'width': '25%', 'targets': 1 },
{ 'width': '120px', 'targets': 2 },
{ 'width': '20%', 'targets': 3 },
{ 'width': '20%', 'targets': 4 },
]
ordering: true
order: [[ 1, 'asc' ]]
dom: '<>fr<"uds-table"t>ip'
language: gui.config.dataTablesLanguage
)
$('.goLink').on('click', (event) ->
$this = $(this);
event.preventDefault();
gui.lookupUuid = $this.attr('href').substr(1)
$(modalId).modal('hide')
setTimeout( ->
$(".lnk-deployed_services").click();
, 500);
)
return
select: (vals, value, btn, tbl, refreshFnc) ->
unless vals.length == 1
$(btn).addClass("disabled").prop('disabled', true)
return
$(btn).removeClass("disabled").prop('disabled', false)
return
}
"delete"
"xls"
]

View File

@ -3,9 +3,6 @@ gui.providers = new GuiElement(api.providers, "provi")
gui.providers.link = (event) ->
"use strict"
iconAndText = (icon, text) ->
'<span class="fa ' + icon + '"> </span> <span class="label-tbl-button">' + text + '</span>'
# Button definition to trigger "Test" action
testButton = testButton:
text: gettext("Test")
@ -112,7 +109,7 @@ gui.providers.link = (event) ->
"new"
"edit"
{
text: iconAndText( 'fa-info', gettext('Information') )
text: gui.tools.iconAndText( 'fa-info', gettext('Information') )
css: "disabled"
disabled: true
click: (vals, value, btn, tbl, refreshFnc) ->
@ -204,7 +201,7 @@ gui.providers.link = (event) ->
"edit"
{
permission: api.permissions.MANAGEMENT
text: iconAndText('fa-ambulance', gettext("Maintenance"))
text: gui.tools.iconAndText('fa-ambulance', gettext("Maintenance"))
css: "disabled"
disabled: true
click: (vals, value, btn, tbl, refreshFnc) ->
@ -230,14 +227,14 @@ gui.providers.link = (event) ->
select: (vals, value, btn, tbl, refreshFnc) ->
unless vals.length == 1
$(btn).removeClass("btn-warning").removeClass("btn-info").addClass("disabled").prop('disabled', true)
$(btn).empty().append(iconAndText('fa-ambulance', gettext("Maintenance")))
$(btn).empty().append(gui.tools.iconAndText('fa-ambulance', gettext("Maintenance")))
return
val = vals[0]
if val.maintenance_mode is false
content = iconAndText('fa-ambulance', gettext('Enter maintenance Mode'))
content = gui.tools.iconAndText('fa-ambulance', gettext('Enter maintenance Mode'))
cls = 'btn-warning'
else
content = iconAndText('fa-truck',gettext('Exit Maintenance Mode'))
content = gui.tools.iconAndText('fa-truck',gettext('Exit Maintenance Mode'))
cls = 'btn-info'
$(btn).removeClass("disabled").addClass(cls).prop('disabled', false)

View File

@ -173,4 +173,7 @@
(data, type, full) ->
levels[data] or "OTHER"
iconAndText: (icon, text) ->
'<span class="fa ' + icon + '"> </span> <span class="label-tbl-button">' + text + '</span>'
return

View File

@ -193,6 +193,7 @@
{% js_template 'providers' %}
{% js_template 'service-info' %}
{% js_template 'authenticators' %}
{% js_template 'user-info' %}
{% js_template 'osmanagers' %}
{% js_template 'connectivity' %}
{% js_template 'services_pool' %}

View File

@ -0,0 +1,86 @@
{% load i18n html5 %}
{% verbatim %}
<ul class="nav nav-tabs">
<li class="active in"><a href="#{{ id }}-overview_tab" data-toggle="tab">{% endverbatim %}{% trans 'Groups' %}{% verbatim %}</a></li>
<li><a href="#{{ id }}-pools_tab" data-toggle="tab">{% endverbatim %}{% trans 'Services Pools' %}{% verbatim %}</a></li>
<li><a href="#{{ id }}-uservices_tab" data-toggle="tab">{% endverbatim %}{% trans 'Assigned Services' %}{% verbatim %}</a></li>
</ul>
<div class="tab-content">
<div class="tab-pane fade in active" id="{{ id }}-overview_tab">
<div class="row">
<div class="col-xs-12">
<table id="{{ id }}-groups-table" style="width:100%;" class="display">
<thead>
<tr>
<th>{% endverbatim %}{% trans 'Group' %}{% verbatim %}</th>
</tr>
</thead>
<tbody>
{{#each groups_all }}
{{# ifbelongs id ../groups }}
<tr>
<td>{{ name }}</td>
</tr>
{{/ ifbelongs }}
{{/each }}
</tbody>
</table>
</div>
</div>
</div>
<div class="tab-pane fade" id="{{ id }}-pools_tab">
<div class="row">
<div class="col-xs-12">
<table id="{{ id }}-pools-table" style="width:100%;" class="display">
<thead>
<tr>
<th>{% endverbatim %}{% trans 'Pool' %}{% verbatim %}</th>
<th>{% endverbatim %}{% trans 'State' %}{% verbatim %}</th>
<th>{% endverbatim %}{% trans 'Image' %}{% verbatim %}</th>
<th></th>
</tr>
</thead>
<tbody>
{{#each pools }}
<tr>
<td>{{ name }}<span style="float: right;"><a href="#{{ id }}" class="{{ ../goClass }}"><i class="fa fa-external-link"> </i></a></span></td>
<td>{{ state }}</td>
<td><img src="data:image/png;base64,{{ thumb }}" style="width: 32px; height: auto;"/></td>
<td>{{ user_services_count }}</td>
</tr>
{{/each }}
</tbody>
</table>
</div>
</div>
</div>
<div class="tab-pane fade" id="{{ id }}-uservices_tab">
<div class="row">
<div class="col-xs-12">
<table id="{{ id }}-userservices-table" style="width:100%;" class="display">
<thead>
<tr>
<th>{% endverbatim %}{% trans 'Unique ID' %}{% verbatim %}</th>
<th>{% endverbatim %}{% trans 'Friendly Name' %}{% verbatim %}</th>
<th>{% endverbatim %}{% trans 'In Use' %}{% verbatim %}</th>
<th>{% endverbatim %}{% trans 'IP' %}{% verbatim %}</th>
<th>{% endverbatim %}{% trans 'Service Pool' %}{% verbatim %}</th>
</tr>
</thead>
<tbody>
{{#each userServices }}
<tr>
<td>{{ unique_id }}</td>
<td>{{ friendly_name }}</td>
<td>{{#if in_use }}{% endverbatim %}{% trans 'Yes' %}{% verbatim %}{{ else }}{% endverbatim %}{% trans 'No' %}{% verbatim %}{{/if }}</td>
<td>{{ ip }}</td>
<td>{{ pool }}<span style="float: right;"><a href="#{{ pool_id }}" class="{{ ../goClass }}"><i class="fa fa-external-link"> </i></a></span></td>
</tr>
{{/each }}
</tbody>
</table>
</div>
</div>
</div>
</div>
{% endverbatim %}

View File

@ -9,30 +9,30 @@
<div class="row">
<div class="col-md-8 col-md-offset-2 bg-primary img-rounded">
<h3>{% trans 'Download UDS Plugin for' %} {{ os|osName }}</h3>
<p>{% trans 'In order to be able to execute UDS services, you need to have UDS plugin installed.' %}</p>
<p>{% trans 'In order to be able to execute UDS services, you need to download and install UDS Plugin.' %}</p>
<div class="text-center">{{ os|pluginDownloadUrl|safe }}</div>
<h3>{% trans 'Or download another version' %}</h3>
<p>{% trans 'If your platform couldnt be detected correctly, you can manually download the version required for your Operating System.' %}</p>
<h3>{% trans 'Or download for other operating system' %}</h3>
<p>{% trans 'In case that your operating system has not been correctly detected, you can download manually from' %}</p>
<p>
{% if os != 'linux' %}
<p class="text-center">
<a href="{% url 'uds.web.views.client_downloads' os='Linux' %}" class="btn btn-warning">{% trans 'Linux UDS plugin' %}</a>
<a href="{% url 'uds.web.views.client_downloads' os='Linux' %}" class="btn btn-warning">{% trans 'Download Linux UDS plugin' %}</a>
</p>
{% endif %}
{% if os != 'windows' %}
<p class="text-center">
<a href="{% url 'uds.web.views.client_downloads' os='Windows' %}" class="btn btn-warning">{% trans 'Windows UDS plugin' %}</a>
<a href="{% url 'uds.web.views.client_downloads' os='Windows' %}" class="btn btn-warning">{% trans 'Download Windows UDS plugin' %}</a>
</p>
{% endif %}
{% if os != 'mac' %}
<p class="text-center">
<a href="{% url 'uds.web.views.client_downloads' os='Mac' %}" class="btn btn-warning">{% trans 'Mac OSX (>10.5) UDS plugin' %}</a>
<a href="{% url 'uds.web.views.client_downloads' os='Mac' %}" class="btn btn-warning">{% trans 'Download Mac OS X (>10.5) UDS plugin' %}</a>
</p>
{% endif %}
</p>
{% if request.user %}
<p>{% trans 'If you already have UDS Plugin installed and you can still see this message, you can disable automatic detection here.' %}</p>
<p>{% trans 'If you already have UDS Plugin installed but this message persists to appear, you can disable automatic detection here' %}</p>
<p>
<form>
<select id="plugin" class="selectpicker show-menu-arrow" data-width="100%" data-size="2" style="display: none;">

View File

@ -211,11 +211,11 @@ def ifbrowser(parser, token):
@register.filter(name='osName')
def osName(os):
if os == 'windows':
return 'Windows platform'
return 'Windows'
elif os == 'linux':
return 'Linux platform'
return 'Linux'
else:
return 'Mac OSX platform'
return 'Mac OS X'
@register.filter(name='pluginDownloadUrl')