* Admin/Preferences: allow to use templates for creating application-passwords (and optionally limit groups to just use pre-existing templates)

This commit is contained in:
ralf 2025-02-18 12:12:44 +01:00
parent 4a1eb59e9d
commit 66a4baf75f
7 changed files with 61 additions and 4 deletions

View File

@ -42,6 +42,19 @@ class Token
$this->token = new Api\Auth\Token();
}
/**
* Allow to use only (preexisting, admin-created) templates to create new token
*
* @return bool
*/
public static function templatesOnly()
{
return static::APP !== 'admin' &&
!empty($GLOBALS['egw_info']['server']['limit_application_password_templates']) &&
array_intersect($GLOBALS['egw']->accounts->memberships($GLOBALS['egw_info']['user']['account_id'], true),
(array)$GLOBALS['egw_info']['server']['limit_application_password_templates']);
}
/**
* Edit or add a token
*
@ -49,6 +62,7 @@ class Token
*/
public function edit(array $content=null)
{
$readonlys = [];
if (!is_array($content))
{
if (!empty($_GET['token_id']))
@ -57,6 +71,21 @@ class Token
{
Api\Framework::window_close(lang('Token not found!'));
}
// opening a template outside admin app
if (static::APP !== 'admin' && !$content['account_id'] && empty($content['token_hash']) && empty($content['token_revoked']))
{
$content['new_token'] = true;
// treat valid_until as relative to creation date
if (!empty($content['token_valid_until']))
{
$content['token_valid_until'] = new Api\DateTime(time()+strtotime($content['token_valid_until'])-strtotime($content['token_created']));
}
unset($content['token_id'], $content['token_created'], $content['token_remark']);
// all fields, but buttons and password are readonly
$readonlys['__ALL__'] = true;
$readonlys['button[save]'] = $readonlys['button[apply]'] = $readonlys['button[cancel]'] =
$readonlys['password'] = $readonlys['token_remark'] = false;
}
}
else
{
@ -84,7 +113,7 @@ class Token
case 'save':
case 'apply':
$content['token_limits'] = Api\Auth\Token::apps2limits($content['token_apps']);
if (empty($content['token_id']) || $content['new_token'])
if (empty($content['token_id']) && static::APP !== 'admin' || $content['new_token'])
{
$content['new_token'] = true;
$button = 'apply'; // must not close window to show token
@ -123,7 +152,7 @@ class Token
$content['token_apps'] = Api\Auth\Token::limits2apps($content['token_limits']);
$content['admin'] = !empty($GLOBALS['egw_info']['user']['apps']['admin']) && static::APP === 'admin';
if (empty($content['account_id'])) $content['account_id'] = '';
$readonlys = [
$readonlys += [
'button[delete]' => !$content['token_id'],
'account_id' => empty($GLOBALS['egw_info']['user']['apps']['admin']) || static::APP !== 'admin',
];
@ -149,9 +178,10 @@ class Token
function get_rows($query,&$rows,&$readonlys,$join='',$need_full_no_count=false,$only_keys=false,$extra_cols=array())
{
// do NOT show all users or other users to non-admin or regular user UI
// show templates (account_id=0 AND token_hash='')
if (empty($GLOBALS['egw_info']['user']['apps']['admin']) || static::APP !== 'admin')
{
$query['col_filter']['account_id'] = $GLOBALS['egw_info']['user']['account_id'];
$query['col_filter'][] = "(account_id=0 AND token_hash='' AND token_revoked IS NULL OR account_id=".(int)$GLOBALS['egw_info']['user']['account_id'].')';
}
// sort revoked token behind active ones
if (empty($query['order']) || $query['order'] === 'token_id')
@ -172,6 +202,10 @@ class Token
{
$row['class'] = 'revoked';
}
elseif (!$row['account_id'] && empty($row['token_hash']))
{
$row['class'] = 'template';
}
}
return $this->token->total;
}
@ -259,7 +293,7 @@ class Token
'caption' => 'Revoke',
'confirm' => 'Revoke this token',
'icon' => 'delete',
'disableClass' => 'revoked',
'disableClass' => static::APP !== 'admin' ? ['template', 'revoked'] : 'revoked',
'group' => $group,
],
];
@ -274,6 +308,14 @@ class Token
unset($actions[$action]['url'], $actions[$action]['popup']);
}
}
// are users allowed to create arbitrary tokens (and edit them), or only new ones from templates
if (self::templatesOnly())
{
unset($actions['add']);
$actions['edit']['caption'] = 'Create';
$actions['edit']['enableClass'] = 'template';
$actions['edit']['icon'] = 'add';
}
return $actions;
}

View File

@ -215,6 +215,9 @@ tr.revoked > td * {
color: grey !important;
font-style: italic;
}
tr.template > td * {
color: darkblue !important;
}
td.token {
border: 3px solid red;
}

View File

@ -103,6 +103,7 @@ it sets content size (text only) according to selected size. preferences de Stel
just clicking on the line, like a checkbox preferences de Einfaches anklicken der Zeile, wie eine Checkbox
keep list open for selecting multiple preferences de Liste für die Auswahl mehrerer Optionen offen halten
language preferences de Sprache
limit following groups to only create application passwords via templates preferences de Beschränke die folgenden Gruppen darauf nur Anwendungspasswörter aus Vorlagen generieren zu dürfen
logging in via singlesignon does not provide a password to pass it on to mail- or file-servers. common de Das Anmelden per SingleSignOn liefert kein Passwort das an Mail- oder Datei-Server weiter gegeben werden kann.
look & feel preferences de Aussehen und Handhabung
lowercase letters preferences de Kleinbuchstaben

View File

@ -103,6 +103,7 @@ it sets content size (text only) according to selected size. preferences en It s
just clicking on the line, like a checkbox preferences en Just clicking on the line, like a checkbox
keep list open for selecting multiple preferences en Keep list open for selecting multiple
language preferences en Language
limit following groups to only create application passwords via templates preferences en Limit following groups to only create application passwords via templates
logging in via singlesignon does not provide a password to pass it on to mail- or file-servers. common en Logging in via SingleSignOn does not provide a password to pass it on to mail- or file-servers.
look & feel preferences en Look & feel
lowercase letters preferences en lowercase letters

View File

@ -59,6 +59,9 @@ class Token extends Admin\Token
],
'sel_options' => [
],
'readonlys' => [
'token[add]' => self::templatesOnly(),
],
'save_callback' => __CLASS__.'::save_callback',
];
}

View File

@ -114,6 +114,9 @@ tr.revoked > td * {
color: grey !important;
font-style: italic;
}
tr.template > td * {
color: darkblue !important;
}
td.token {
border: 3px solid red;
}

View File

@ -28,6 +28,10 @@
<et2-description value="Deny following groups access to application passwords" label="%s:"></et2-description>
<et2-select-account id="newsettings[deny_application_passwords]" multiple="true" width="100%" accountType="groups"></et2-select-account>
</row>
<row>
<et2-description value="Limit following groups to only create application passwords via templates" label="%s:"></et2-description>
<et2-select-account id="newsettings[limit_application_password_templates]" multiple="true" width="100%" accountType="groups"></et2-select-account>
</row>
</rows>
</grid>
</template>