mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Show the login roles that are members of a group role be shown when examining a group role. Fixes #5404
This commit is contained in:
parent
68132e2a8f
commit
7bad4ca535
Binary file not shown.
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 80 KiB |
@ -9,6 +9,7 @@ This release contains a number of bug fixes and new features since the release o
|
|||||||
New features
|
New features
|
||||||
************
|
************
|
||||||
|
|
||||||
|
| `Issue #5404 <https://redmine.postgresql.org/issues/5404>`_ - Show the login roles that are members of a group role be shown when examining a group role.
|
||||||
| `Issue #6268 <https://redmine.postgresql.org/issues/6268>`_ - Make 'kerberos' an optional feature in the Python wheel, to avoid the need to install MIT Kerberos on the system by default.
|
| `Issue #6268 <https://redmine.postgresql.org/issues/6268>`_ - Make 'kerberos' an optional feature in the Python wheel, to avoid the need to install MIT Kerberos on the system by default.
|
||||||
| `Issue #6270 <https://redmine.postgresql.org/issues/6270>`_ - Added '--replace' option in Import server to replace the list of servers with the newly imported one.
|
| `Issue #6270 <https://redmine.postgresql.org/issues/6270>`_ - Added '--replace' option in Import server to replace the list of servers with the newly imported one.
|
||||||
|
|
||||||
|
@ -71,11 +71,11 @@ Use the *Privileges* tab to grant privileges to the role.
|
|||||||
:alt: Role dialog membership tab
|
:alt: Role dialog membership tab
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
* Specify members of the role in the *Role Membership* field. Click inside the
|
* Specify member of the role in the *Member of* field and specify the members in the *Member* field.
|
||||||
*Roles* field to select role names from a drop down list. Confirm each
|
Confirm each selection by checking the checkbox to the right of the role name;
|
||||||
selection by checking the checkbox to the right of the role name; delete a
|
delete a selection by clicking the *x* to the left of the role name.
|
||||||
selection by clicking the *x* to the left of the role name. Membership conveys
|
Membership conveys the privileges granted to the specified role to each of
|
||||||
the privileges granted to the specified role to each of its members.
|
its members.
|
||||||
|
|
||||||
Click the *Parameters* tab to continue.
|
Click the *Parameters* tab to continue.
|
||||||
|
|
||||||
|
@ -236,6 +236,105 @@ class RoleView(PGChildNodeView):
|
|||||||
data['rolmembership'].get('deleted', []),
|
data['rolmembership'].get('deleted', []),
|
||||||
lambda _: True, 'role')
|
lambda _: True, 'role')
|
||||||
|
|
||||||
|
def _process_rolmembers(self, id, data):
|
||||||
|
"""
|
||||||
|
Parser role members.
|
||||||
|
:param id:
|
||||||
|
:param data:
|
||||||
|
"""
|
||||||
|
def _part_dict_list(dict_list, condition, list_key=None):
|
||||||
|
ret_val = []
|
||||||
|
for d in dict_list:
|
||||||
|
if condition(d):
|
||||||
|
ret_val.append(d[list_key])
|
||||||
|
|
||||||
|
return ret_val
|
||||||
|
if id == -1:
|
||||||
|
data['rol_members'] = []
|
||||||
|
data['rol_admins'] = []
|
||||||
|
|
||||||
|
data['rol_admins'] = _part_dict_list(
|
||||||
|
data['rolmembers'], lambda d: d['admin'], 'role')
|
||||||
|
data['rol_members'] = _part_dict_list(
|
||||||
|
data['rolmembers'], lambda d: not d['admin'], 'role')
|
||||||
|
else:
|
||||||
|
data['rol_admins'] = _part_dict_list(
|
||||||
|
data['rolmembers'].get('added', []),
|
||||||
|
lambda d: d['admin'], 'role')
|
||||||
|
data['rol_members'] = _part_dict_list(
|
||||||
|
data['rolmembers'].get('added', []),
|
||||||
|
lambda d: not d['admin'], 'role')
|
||||||
|
|
||||||
|
data['rol_admins'].extend(_part_dict_list(
|
||||||
|
data['rolmembers'].get('changed', []),
|
||||||
|
lambda d: d['admin'], 'role'))
|
||||||
|
data['rol_revoked_admins'] = _part_dict_list(
|
||||||
|
data['rolmembers'].get('changed', []),
|
||||||
|
lambda d: not d['admin'], 'role')
|
||||||
|
|
||||||
|
data['rol_revoked'] = _part_dict_list(
|
||||||
|
data['rolmembers'].get('deleted', []),
|
||||||
|
lambda _: True, 'role')
|
||||||
|
|
||||||
|
def _validate_rolemembers(self, id, data):
|
||||||
|
"""
|
||||||
|
Validate the rolmembers data dict
|
||||||
|
:param data: role data
|
||||||
|
:return: valid or invalid message
|
||||||
|
"""
|
||||||
|
if 'rolmembers' not in data:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if id == -1:
|
||||||
|
msg = _("""
|
||||||
|
Role members information must be passed as an array of JSON objects in the
|
||||||
|
following format:
|
||||||
|
|
||||||
|
rolmembers:[{
|
||||||
|
role: [rolename],
|
||||||
|
admin: True/False
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]""")
|
||||||
|
|
||||||
|
if not self._validate_input_dict_for_new(data['rolmembers'],
|
||||||
|
['role', 'admin']):
|
||||||
|
return msg
|
||||||
|
|
||||||
|
self._process_rolmembers(id, data)
|
||||||
|
return None
|
||||||
|
|
||||||
|
msg = _("""
|
||||||
|
Role membership information must be passed as a string representing an array of
|
||||||
|
JSON objects in the following format:
|
||||||
|
rolmembers:{
|
||||||
|
'added': [{
|
||||||
|
role: [rolename],
|
||||||
|
admin: True/False
|
||||||
|
},
|
||||||
|
...
|
||||||
|
],
|
||||||
|
'deleted': [{
|
||||||
|
role: [rolename],
|
||||||
|
admin: True/False
|
||||||
|
},
|
||||||
|
...
|
||||||
|
],
|
||||||
|
'updated': [{
|
||||||
|
role: [rolename],
|
||||||
|
admin: True/False
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]
|
||||||
|
""")
|
||||||
|
if not self._validate_input_dict_for_update(data['rolmembers'],
|
||||||
|
['role', 'admin'],
|
||||||
|
['role']):
|
||||||
|
return msg
|
||||||
|
|
||||||
|
self._process_rolmembers(id, data)
|
||||||
|
return None
|
||||||
|
|
||||||
def _validate_rolemembership(self, id, data):
|
def _validate_rolemembership(self, id, data):
|
||||||
"""
|
"""
|
||||||
Validate the rolmembership data dict
|
Validate the rolmembership data dict
|
||||||
@ -433,7 +532,7 @@ rolmembership:{
|
|||||||
'rolcanlogin', 'rolsuper', 'rolcreatedb',
|
'rolcanlogin', 'rolsuper', 'rolcreatedb',
|
||||||
'rolcreaterole', 'rolinherit', 'rolreplication',
|
'rolcreaterole', 'rolinherit', 'rolreplication',
|
||||||
'rolcatupdate', 'variables', 'rolmembership',
|
'rolcatupdate', 'variables', 'rolmembership',
|
||||||
'seclabels'
|
'seclabels', 'rolmembers'
|
||||||
]:
|
]:
|
||||||
data[key] = json.loads(val, encoding='utf-8')
|
data[key] = json.loads(val, encoding='utf-8')
|
||||||
else:
|
else:
|
||||||
@ -466,6 +565,11 @@ rolmembership:{
|
|||||||
if invalid_msg is not None:
|
if invalid_msg is not None:
|
||||||
return precondition_required(invalid_msg)
|
return precondition_required(invalid_msg)
|
||||||
|
|
||||||
|
invalid_msg = self._validate_rolemembers(
|
||||||
|
kwargs.get('rid', -1), data)
|
||||||
|
if invalid_msg is not None:
|
||||||
|
return precondition_required(invalid_msg)
|
||||||
|
|
||||||
self.request = data
|
self.request = data
|
||||||
|
|
||||||
return f(self, **kwargs)
|
return f(self, **kwargs)
|
||||||
@ -716,6 +820,16 @@ rolmembership:{
|
|||||||
})
|
})
|
||||||
row['seclabels'] = res
|
row['seclabels'] = res
|
||||||
|
|
||||||
|
if 'rolmembers' in row:
|
||||||
|
rolmembers = []
|
||||||
|
for role in row['rolmembers']:
|
||||||
|
role = re.search(r'([01])(.+)', role)
|
||||||
|
rolmembers.append({
|
||||||
|
'role': role.group(2),
|
||||||
|
'admin': True if role.group(1) == '1' else False
|
||||||
|
})
|
||||||
|
row['rolmembers'] = rolmembers
|
||||||
|
|
||||||
@check_precondition(action='properties')
|
@check_precondition(action='properties')
|
||||||
def properties(self, gid, sid, rid):
|
def properties(self, gid, sid, rid):
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ define('pgadmin.node.role', [
|
|||||||
template: _.template([
|
template: _.template([
|
||||||
'<label class="<%=Backform.controlLabelClassName%>"><%=label%></label>',
|
'<label class="<%=Backform.controlLabelClassName%>"><%=label%></label>',
|
||||||
'<div class="<%=Backform.controlsClassName%>">',
|
'<div class="<%=Backform.controlsClassName%>">',
|
||||||
' <select title = <%=label%> multiple="multiple" style="width:100%;" class="pgadmin-controls <%=extraClasses.join(\' \')%>" name="<%=name%>" value="<%-JSON.stringify(value)%>" <%=disabled ? "disabled" : ""%> <%=required ? "required" : ""%>>',
|
' <select title = <%=label%> multiple="multiple" style="width:100%;" class="pgadmin-controls <%=extraClasses.join(\' \')%>" name="<%=name%>" value="<%-JSON.stringify(value)%>" <%=disabled ? "disabled" : ""%> <%=readonly ? "readonly" : ""%> <%=required ? "required" : ""%>>',
|
||||||
' <% for (var i=0; i < options.length; i++) { %>',
|
' <% for (var i=0; i < options.length; i++) { %>',
|
||||||
' <% var option = options[i]; %>',
|
' <% var option = options[i]; %>',
|
||||||
' <option value=<%-option.value%> data-icon=<%-option.image%> <%=value != null && _.indexOf(value, option.value) != -1 ? "selected" : ""%> <%=option.disabled ? "disabled=\'disabled\'" : ""%>><%-option.label%></option>',
|
' <option value=<%-option.value%> data-icon=<%-option.image%> <%=value != null && _.indexOf(value, option.value) != -1 ? "selected" : ""%> <%=option.disabled ? "disabled=\'disabled\'" : ""%>><%-option.label%></option>',
|
||||||
@ -107,7 +107,7 @@ define('pgadmin.node.role', [
|
|||||||
' <span><%= opttext %><span>',
|
' <span><%= opttext %><span>',
|
||||||
' <% if (checkbox) { %>',
|
' <% if (checkbox) { %>',
|
||||||
' <div class="custom-control custom-checkbox custom-checkbox-no-label d-inline">',
|
' <div class="custom-control custom-checkbox custom-checkbox-no-label d-inline">',
|
||||||
' <input tabindex="-1" type="checkbox" class="custom-control-input" id="check_<%= opttext %>" />',
|
' <input tabindex="-1" type="checkbox" class="custom-control-input" id="check_<%= opttext %>" <%=disabled ? "disabled" : ""%> />',
|
||||||
' <label class="custom-control-label" for="check_<%= opttext %>">',
|
' <label class="custom-control-label" for="check_<%= opttext %>">',
|
||||||
' <span class="sr-only">WITH ADMIN<span>',
|
' <span class="sr-only">WITH ADMIN<span>',
|
||||||
' </label>',
|
' </label>',
|
||||||
@ -149,6 +149,7 @@ define('pgadmin.node.role', [
|
|||||||
_.extend(data, {
|
_.extend(data, {
|
||||||
disabled: evalF(data.disabled, data, this.model),
|
disabled: evalF(data.disabled, data, this.model),
|
||||||
visible: evalF(data.visible, data, this.model),
|
visible: evalF(data.visible, data, this.model),
|
||||||
|
readonly: evalF(data.readonly, data, this.model),
|
||||||
required: evalF(data.required, data, this.model),
|
required: evalF(data.required, data, this.model),
|
||||||
helpMessage: evalASFunc(data.helpMessage, data, this.model),
|
helpMessage: evalASFunc(data.helpMessage, data, this.model),
|
||||||
});
|
});
|
||||||
@ -242,7 +243,7 @@ define('pgadmin.node.role', [
|
|||||||
multiple: true,
|
multiple: true,
|
||||||
tags: true,
|
tags: true,
|
||||||
allowClear: data.disabled ? false : true,
|
allowClear: data.disabled ? false : true,
|
||||||
placeholder: data.disabled ? '' : gettext('Select members'),
|
placeholder: data.disabled ? '' : gettext('Select roles'),
|
||||||
width: 'style',
|
width: 'style',
|
||||||
}).on('change', function(e) {
|
}).on('change', function(e) {
|
||||||
$(e.target).find(':selected').each(function() {
|
$(e.target).find(':selected').each(function() {
|
||||||
@ -386,6 +387,7 @@ define('pgadmin.node.role', [
|
|||||||
rolcatupdate: false,
|
rolcatupdate: false,
|
||||||
rolreplication: false,
|
rolreplication: false,
|
||||||
rolmembership: [],
|
rolmembership: [],
|
||||||
|
rolmembers: [],
|
||||||
rolvaliduntil: null,
|
rolvaliduntil: null,
|
||||||
seclabels: [],
|
seclabels: [],
|
||||||
variables: [],
|
variables: [],
|
||||||
@ -492,11 +494,12 @@ define('pgadmin.node.role', [
|
|||||||
controlsClassName: 'pgadmin-controls pg-el-sm-8 pg-el-12',
|
controlsClassName: 'pgadmin-controls pg-el-sm-8 pg-el-12',
|
||||||
min_version: 90100,
|
min_version: 90100,
|
||||||
readonly: 'readonly',
|
readonly: 'readonly',
|
||||||
},{
|
},
|
||||||
id: 'rolmembership', label: gettext('Roles'),
|
{
|
||||||
|
id: 'rolmembership', label: gettext('Member of'),
|
||||||
group: gettext('Membership'), type: 'collection',
|
group: gettext('Membership'), type: 'collection',
|
||||||
cell: 'string', readonly: 'readonly',
|
cell: 'string', mode: ['properties', 'edit', 'create'],
|
||||||
mode: ['properties', 'edit', 'create'],
|
readonly: 'readonly',
|
||||||
control: RoleMembersControl, model: pgBrowser.Node.Model.extend({
|
control: RoleMembersControl, model: pgBrowser.Node.Model.extend({
|
||||||
keys: ['role'],
|
keys: ['role'],
|
||||||
idAttribute: 'role',
|
idAttribute: 'role',
|
||||||
@ -518,7 +521,34 @@ define('pgadmin.node.role', [
|
|||||||
return gettext('Roles shown with a check mark have the WITH ADMIN OPTION set.');
|
return gettext('Roles shown with a check mark have the WITH ADMIN OPTION set.');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},{
|
},
|
||||||
|
{
|
||||||
|
id: 'rolmembers', label: gettext('Members'), type: 'collection', group: gettext('Membership'),
|
||||||
|
mode: ['properties', 'edit', 'create'], cell: 'string',
|
||||||
|
readonly: 'readonly',
|
||||||
|
control: RoleMembersControl, model: pgBrowser.Node.Model.extend({
|
||||||
|
keys: ['role'],
|
||||||
|
idAttribute: 'role',
|
||||||
|
defaults: {
|
||||||
|
role: undefined,
|
||||||
|
admin: false,
|
||||||
|
},
|
||||||
|
validate: function() {
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
filter: function(d) {
|
||||||
|
return this.model.isNew() || (this.model.get('rolname') != d.label);
|
||||||
|
},
|
||||||
|
helpMessage: function(m) {
|
||||||
|
if (m.has('read_only') && m.get('read_only') == false) {
|
||||||
|
return gettext('Select the checkbox for roles to include WITH ADMIN OPTION.');
|
||||||
|
} else {
|
||||||
|
return gettext('Roles shown with a check mark have the WITH ADMIN OPTION set.');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
id: 'variables', label: '', type: 'collection',
|
id: 'variables', label: '', type: 'collection',
|
||||||
group: gettext('Parameters'), hasDatabase: true, url: 'variables',
|
group: gettext('Parameters'), hasDatabase: true, url: 'variables',
|
||||||
model: pgBrowser.Node.VariableModel.extend({keys:['name', 'database']}),
|
model: pgBrowser.Node.VariableModel.extend({keys:['name', 'database']}),
|
||||||
|
@ -9,6 +9,15 @@ SELECT
|
|||||||
LEFT JOIN pg_catalog.pg_roles rm ON (rm.oid = am.roleid)
|
LEFT JOIN pg_catalog.pg_roles rm ON (rm.oid = am.roleid)
|
||||||
) rolmembership,
|
) rolmembership,
|
||||||
(SELECT pg_catalog.array_agg(provider || '=' || label) FROM pg_catalog.pg_shseclabel sl1 WHERE sl1.objoid=r.oid) AS seclabels
|
(SELECT pg_catalog.array_agg(provider || '=' || label) FROM pg_catalog.pg_shseclabel sl1 WHERE sl1.objoid=r.oid) AS seclabels
|
||||||
|
{% if rid %}
|
||||||
|
,ARRAY(
|
||||||
|
SELECT
|
||||||
|
CASE WHEN pg.admin_option THEN '1' ELSE '0' END || pg.usename
|
||||||
|
FROM
|
||||||
|
(SELECT pg_roles.rolname AS usename, pg_auth_members.admin_option AS admin_option FROM pg_roles
|
||||||
|
JOIN pg_auth_members ON pg_roles.oid=pg_auth_members.member AND pg_auth_members.roleid={{ rid|qtLiteral }}::oid) pg
|
||||||
|
) rolmembers
|
||||||
|
{% endif %}
|
||||||
FROM
|
FROM
|
||||||
pg_catalog.pg_roles r
|
pg_catalog.pg_roles r
|
||||||
{% if rid %}
|
{% if rid %}
|
||||||
|
@ -124,3 +124,15 @@ GRANT {{ conn|qtIdent(data.members)|join(', ') }} TO {{ conn|qtIdent(rolname) }}
|
|||||||
|
|
||||||
COMMENT ON ROLE {{ conn|qtIdent(rolname) }} IS {{ data.description|qtLiteral }};
|
COMMENT ON ROLE {{ conn|qtIdent(rolname) }} IS {{ data.description|qtLiteral }};
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if 'rol_revoked_admins' in data and
|
||||||
|
data.rol_revoked_admins|length > 0
|
||||||
|
%}
|
||||||
|
|
||||||
|
REVOKE ADMIN OPTION FOR {{ conn|qtIdent(rolname) }} FROM {{ conn|qtIdent(data.rol_revoked_admins)|join(', ') }};{% endif %}{% if 'rol_revoked' in data and data.rol_revoked|length > 0 %}
|
||||||
|
|
||||||
|
REVOKE {{ conn|qtIdent(rolname) }} FROM {{ conn|qtIdent(data.rol_revoked)|join(', ') }};{% endif %}{% if data.rol_admins and data.rol_admins|length > 0 %}
|
||||||
|
|
||||||
|
GRANT {{ conn|qtIdent(rolname) }} TO {{ conn|qtIdent(data.rol_admins)|join(', ') }} WITH ADMIN OPTION;{% endif %}{% if data.rol_members and data.rol_members|length > 0 %}
|
||||||
|
|
||||||
|
GRANT {{ conn|qtIdent(rolname) }} TO {{ conn|qtIdent(data.rol_members)|join(', ') }};{% endif %}
|
||||||
|
@ -10,6 +10,15 @@ SELECT
|
|||||||
ORDER BY rm.rolname
|
ORDER BY rm.rolname
|
||||||
) AS rolmembership,
|
) AS rolmembership,
|
||||||
(SELECT pg_catalog.array_agg(provider || '=' || label) FROM pg_catalog.pg_shseclabel sl1 WHERE sl1.objoid=r.oid) AS seclabels
|
(SELECT pg_catalog.array_agg(provider || '=' || label) FROM pg_catalog.pg_shseclabel sl1 WHERE sl1.objoid=r.oid) AS seclabels
|
||||||
|
{% if rid %}
|
||||||
|
,ARRAY(
|
||||||
|
SELECT
|
||||||
|
CASE WHEN pg.admin_option THEN '1' ELSE '0' END || pg.usename
|
||||||
|
FROM
|
||||||
|
(SELECT pg_roles.rolname AS usename, pg_auth_members.admin_option AS admin_option FROM pg_roles
|
||||||
|
JOIN pg_auth_members ON pg_roles.oid=pg_auth_members.member AND pg_auth_members.roleid={{ rid|qtLiteral }}::oid) pg
|
||||||
|
) rolmembers
|
||||||
|
{% endif %}
|
||||||
FROM
|
FROM
|
||||||
pg_catalog.pg_roles r
|
pg_catalog.pg_roles r
|
||||||
{% if rid %}
|
{% if rid %}
|
||||||
|
@ -99,3 +99,15 @@ GRANT {{ conn|qtIdent(data.members)|join(', ') }} TO {{ conn|qtIdent(rolname) }}
|
|||||||
|
|
||||||
COMMENT ON ROLE {{ conn|qtIdent(rolname) }} IS {{ data.description|qtLiteral }};
|
COMMENT ON ROLE {{ conn|qtIdent(rolname) }} IS {{ data.description|qtLiteral }};
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if 'rol_revoked_admins' in data and
|
||||||
|
data.rol_revoked_admins|length > 0
|
||||||
|
%}
|
||||||
|
|
||||||
|
REVOKE ADMIN OPTION FOR {{ conn|qtIdent(rolname) }} FROM {{ conn|qtIdent(data.rol_revoked_admins)|join(', ') }};{% endif %}{% if 'rol_revoked' in data and data.rol_revoked|length > 0 %}
|
||||||
|
|
||||||
|
REVOKE {{ conn|qtIdent(rolname) }} FROM {{ conn|qtIdent(data.rol_revoked)|join(', ') }};{% endif %}{% if data.rol_admins and data.rol_admins|length > 0 %}
|
||||||
|
|
||||||
|
GRANT {{ conn|qtIdent(rolname) }} TO {{ conn|qtIdent(data.rol_admins)|join(', ') }} WITH ADMIN OPTION;{% endif %}{% if data.rol_members and data.rol_members|length > 0 %}
|
||||||
|
|
||||||
|
GRANT {{ conn|qtIdent(rolname) }} TO {{ conn|qtIdent(data.rol_members)|join(', ') }};{% endif %}
|
||||||
|
@ -117,7 +117,8 @@ select[readonly].select2-hidden-accessible + .select2-container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
select[readonly].select2-hidden-accessible + .select2-container .select2-selection {
|
select[readonly].select2-hidden-accessible + .select2-container .select2-selection {
|
||||||
background: #eee;
|
background: $select2-readonly;
|
||||||
|
color: $text-muted;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,3 +369,5 @@ $erd-link-selected-color: $color-fg !default;
|
|||||||
@return '%23' + str-slice('#{$colour}', 2, -1)
|
@return '%23' + str-slice('#{$colour}', 2, -1)
|
||||||
}
|
}
|
||||||
$erd-bg-grid: url("data:image/svg+xml, %3Csvg width='100%25' viewBox='0 0 45 45' style='background-color:#{url-friendly-colour($erd-canvas-bg)}' height='100%25' xmlns='http://www.w3.org/2000/svg'%3E%3Cdefs%3E%3Cpattern id='smallGrid' width='15' height='15' patternUnits='userSpaceOnUse'%3E%3Cpath d='M 15 0 L 0 0 0 15' fill='none' stroke='#{url-friendly-colour($erd-canvas-grid)}' stroke-width='0.5'/%3E%3C/pattern%3E%3Cpattern id='grid' width='45' height='45' patternUnits='userSpaceOnUse'%3E%3Crect width='100' height='100' fill='url(%23smallGrid)'/%3E%3Cpath d='M 100 0 L 0 0 0 100' fill='none' stroke='#{url-friendly-colour($erd-canvas-grid)}' stroke-width='1'/%3E%3C/pattern%3E%3C/defs%3E%3Crect width='100%25' height='100%25' fill='url(%23grid)' /%3E%3C/svg%3E%0A");
|
$erd-bg-grid: url("data:image/svg+xml, %3Csvg width='100%25' viewBox='0 0 45 45' style='background-color:#{url-friendly-colour($erd-canvas-bg)}' height='100%25' xmlns='http://www.w3.org/2000/svg'%3E%3Cdefs%3E%3Cpattern id='smallGrid' width='15' height='15' patternUnits='userSpaceOnUse'%3E%3Cpath d='M 15 0 L 0 0 0 15' fill='none' stroke='#{url-friendly-colour($erd-canvas-grid)}' stroke-width='0.5'/%3E%3C/pattern%3E%3Cpattern id='grid' width='45' height='45' patternUnits='userSpaceOnUse'%3E%3Crect width='100' height='100' fill='url(%23smallGrid)'/%3E%3Cpath d='M 100 0 L 0 0 0 100' fill='none' stroke='#{url-friendly-colour($erd-canvas-grid)}' stroke-width='1'/%3E%3C/pattern%3E%3C/defs%3E%3Crect width='100%25' height='100%25' fill='url(%23grid)' /%3E%3C/svg%3E%0A");
|
||||||
|
|
||||||
|
$select2-readonly: $color-gray-lighter !default;
|
||||||
|
@ -134,3 +134,5 @@ $erd-canvas-bg: $color-gray-light;
|
|||||||
$erd-canvas-grid: #444952;
|
$erd-canvas-grid: #444952;
|
||||||
$erd-link-color: $color-fg;
|
$erd-link-color: $color-fg;
|
||||||
$erd-link-selected-color: $color-fg;
|
$erd-link-selected-color: $color-fg;
|
||||||
|
|
||||||
|
$select2-readonly: $color-bg;
|
||||||
|
@ -205,3 +205,5 @@ $span-text-color: #9D9FA1 !default;
|
|||||||
$span-text-color-hover: $black !default;
|
$span-text-color-hover: $black !default;
|
||||||
$quick-search-a-text-color: $black !default;
|
$quick-search-a-text-color: $black !default;
|
||||||
$quick-search-info-icon: #8A8A8A !default;
|
$quick-search-info-icon: #8A8A8A !default;
|
||||||
|
|
||||||
|
$select2-readonly: $color-gray;
|
||||||
|
Loading…
Reference in New Issue
Block a user