Added ability to change auth level IO-550
This commit is contained in:
@@ -4089,6 +4089,32 @@
|
|||||||
</concept_node>
|
</concept_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
|
<folder_node>
|
||||||
|
<name>users</name>
|
||||||
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>editaccess</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
</children>
|
||||||
|
</folder_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
@@ -26240,9 +26266,56 @@
|
|||||||
</concept_node>
|
</concept_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
|
<folder_node>
|
||||||
|
<name>errors</name>
|
||||||
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>updating</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
</children>
|
||||||
|
</folder_node>
|
||||||
<folder_node>
|
<folder_node>
|
||||||
<name>fields</name>
|
<name>fields</name>
|
||||||
<children>
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>authlevel</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>displayname</name>
|
<name>displayname</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -26264,6 +26337,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>email</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>photourl</name>
|
<name>photourl</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -26287,6 +26381,32 @@
|
|||||||
</concept_node>
|
</concept_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
|
<folder_node>
|
||||||
|
<name>labels</name>
|
||||||
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>actions</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
</children>
|
||||||
|
</folder_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
<folder_node>
|
<folder_node>
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ const ret = {
|
|||||||
"jobs:intake": 1,
|
"jobs:intake": 1,
|
||||||
"jobs:close": 5,
|
"jobs:close": 5,
|
||||||
"jobs:detail": 1,
|
"jobs:detail": 1,
|
||||||
|
"jobs:partsqueue": 4,
|
||||||
|
|
||||||
"bills:enter": 2,
|
"bills:enter": 2,
|
||||||
"bills:view": 2,
|
"bills:view": 2,
|
||||||
@@ -49,5 +50,8 @@ const ret = {
|
|||||||
|
|
||||||
"timetickets:enter": 3,
|
"timetickets:enter": 3,
|
||||||
"timetickets:list": 3,
|
"timetickets:list": 3,
|
||||||
|
"timetickets:edit": 4,
|
||||||
|
|
||||||
|
"users:editaccess": 4,
|
||||||
};
|
};
|
||||||
export default ret;
|
export default ret;
|
||||||
|
|||||||
@@ -476,6 +476,18 @@ export default function ShopInfoRbacComponent({ form }) {
|
|||||||
>
|
>
|
||||||
<InputNumber />
|
<InputNumber />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.fields.rbac.users.editaccess")}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: t("general.validation.required"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
name={["md_rbac", "users:editaccess"]}
|
||||||
|
>
|
||||||
|
<InputNumber />
|
||||||
|
</Form.Item>
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import { InputNumber, notification } from "antd";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { useMutation } from "react-apollo";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { UPDATE_ASSOCIATION } from "../../graphql/user.queries";
|
||||||
|
|
||||||
|
export default function ShopUsersAuthEdit({ association }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [updateAssociation] = useMutation(UPDATE_ASSOCIATION);
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
const [value, setValue] = useState(association.authlevel);
|
||||||
|
|
||||||
|
const handleSave = async () => {
|
||||||
|
setVisible(false);
|
||||||
|
const result = await updateAssociation({
|
||||||
|
variables: {
|
||||||
|
assocId: association.id,
|
||||||
|
assoc: { authlevel: value },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!!result.errors) {
|
||||||
|
notification["error"]({
|
||||||
|
message: t("user.errors.updating", {
|
||||||
|
message: JSON.stringify(result.errors),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{visible && (
|
||||||
|
<div>
|
||||||
|
<InputNumber
|
||||||
|
min={0}
|
||||||
|
value={value}
|
||||||
|
onChange={(val) => setValue(val)}
|
||||||
|
defaultValue={association.authlevel}
|
||||||
|
onBlur={handleSave}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{!visible && (
|
||||||
|
<div style={{ cursor: "pointer" }} onClick={() => setVisible(true)}>
|
||||||
|
{association.authlevel || t("general.labels.na")}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
59
client/src/components/shop-users/shop-users.component.jsx
Normal file
59
client/src/components/shop-users/shop-users.component.jsx
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import { Button, Table } from "antd";
|
||||||
|
import React from "react";
|
||||||
|
import { useQuery } from "react-apollo";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { QUERY_SHOP_ASSOCIATIONS } from "../../graphql/user.queries";
|
||||||
|
import AlertComponent from "../alert/alert.component";
|
||||||
|
import RbacWrapper from "../rbac-wrapper/rbac-wrapper.component";
|
||||||
|
import ShopUsersAuthEdit from "../shop-users-auth-edit/shop-users-auth-edit.component";
|
||||||
|
|
||||||
|
export default function ShopInfoUsersComponent() {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { loading, error, data } = useQuery(QUERY_SHOP_ASSOCIATIONS);
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: t("user.fields.email"),
|
||||||
|
dataIndex: "email",
|
||||||
|
key: "email",
|
||||||
|
render: (text, record) => record.user.email,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("user.fields.authlevel"),
|
||||||
|
dataIndex: "authlevel",
|
||||||
|
key: "authlevel",
|
||||||
|
render: (text, record) => (
|
||||||
|
<RbacWrapper action="users:editaccess">
|
||||||
|
<ShopUsersAuthEdit association={record} />
|
||||||
|
</RbacWrapper>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("user.labels.actions"),
|
||||||
|
dataIndex: "actions",
|
||||||
|
key: "actions",
|
||||||
|
render: (text, record) => (
|
||||||
|
<div>
|
||||||
|
<Button disabled onClick={() => {}}>
|
||||||
|
{t("general.actions.delete")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return <AlertComponent type="error" message={JSON.stringify(error)} />;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Table
|
||||||
|
loading={loading}
|
||||||
|
size="small"
|
||||||
|
pagination={{ position: "top" }}
|
||||||
|
columns={columns.map((item) => ({ ...item }))}
|
||||||
|
rowKey="id"
|
||||||
|
dataSource={data && data.associations}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,5 +1,36 @@
|
|||||||
import gql from "graphql-tag";
|
import gql from "graphql-tag";
|
||||||
|
|
||||||
|
export const QUERY_SHOP_ASSOCIATIONS = gql`
|
||||||
|
query QUERY_SHOP_ASSOCIATIONS {
|
||||||
|
associations {
|
||||||
|
id
|
||||||
|
authlevel
|
||||||
|
shopid
|
||||||
|
user {
|
||||||
|
email
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const UPDATE_ASSOCIATION = gql`
|
||||||
|
mutation UPDATE_ASSOCIATION(
|
||||||
|
$assocId: uuid!
|
||||||
|
$assoc: associations_set_input!
|
||||||
|
) {
|
||||||
|
update_associations(where: { id: { _eq: $assocId } }, _set: $assoc) {
|
||||||
|
returning {
|
||||||
|
id
|
||||||
|
authlevel
|
||||||
|
shopid
|
||||||
|
user {
|
||||||
|
email
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
export const UPSERT_USER = gql`
|
export const UPSERT_USER = gql`
|
||||||
mutation UPSERT_USER($authEmail: String!, $authToken: String!) {
|
mutation UPSERT_USER($authEmail: String!, $authToken: String!) {
|
||||||
insert_users(
|
insert_users(
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
setBreadcrumbs,
|
setBreadcrumbs,
|
||||||
} from "../../redux/application/application.actions";
|
} from "../../redux/application/application.actions";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
|
import ShopInfoUsersComponent from "../../components/shop-users/shop-users.component";
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
});
|
});
|
||||||
@@ -42,7 +43,7 @@ export function ShopPage({ bodyshop, setSelectedHeader, setBreadcrumbs }) {
|
|||||||
<ShopEmployeesContainer />
|
<ShopEmployeesContainer />
|
||||||
</Tabs.TabPane>
|
</Tabs.TabPane>
|
||||||
<Tabs.TabPane tab={t("bodyshop.labels.licensing")} key="licensing">
|
<Tabs.TabPane tab={t("bodyshop.labels.licensing")} key="licensing">
|
||||||
Licensing
|
<ShopInfoUsersComponent />
|
||||||
</Tabs.TabPane>
|
</Tabs.TabPane>
|
||||||
<Tabs.TabPane tab={t("bodyshop.labels.csiq")} key="csiq">
|
<Tabs.TabPane tab={t("bodyshop.labels.csiq")} key="csiq">
|
||||||
<ShopCsiConfig />
|
<ShopCsiConfig />
|
||||||
|
|||||||
@@ -280,6 +280,9 @@
|
|||||||
"edit": "Time Tickets -> Edit",
|
"edit": "Time Tickets -> Edit",
|
||||||
"enter": "Time Tickets -> Enter",
|
"enter": "Time Tickets -> Enter",
|
||||||
"list": "Time Tickets -> List"
|
"list": "Time Tickets -> List"
|
||||||
|
},
|
||||||
|
"users": {
|
||||||
|
"editaccess": "Users -> Edit access"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"responsibilitycenter": "Responsibility Center",
|
"responsibilitycenter": "Responsibility Center",
|
||||||
@@ -1616,9 +1619,17 @@
|
|||||||
"signout": "Sign Out",
|
"signout": "Sign Out",
|
||||||
"updateprofile": "Update Profile"
|
"updateprofile": "Update Profile"
|
||||||
},
|
},
|
||||||
|
"errors": {
|
||||||
|
"updating": "Error updating user or association {{message}}"
|
||||||
|
},
|
||||||
"fields": {
|
"fields": {
|
||||||
|
"authlevel": "Authorization Level",
|
||||||
"displayname": "Display Name",
|
"displayname": "Display Name",
|
||||||
|
"email": "Email",
|
||||||
"photourl": "Avatar URL"
|
"photourl": "Avatar URL"
|
||||||
|
},
|
||||||
|
"labels": {
|
||||||
|
"actions": "Actions"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"vehicles": {
|
"vehicles": {
|
||||||
|
|||||||
@@ -280,6 +280,9 @@
|
|||||||
"edit": "",
|
"edit": "",
|
||||||
"enter": "",
|
"enter": "",
|
||||||
"list": ""
|
"list": ""
|
||||||
|
},
|
||||||
|
"users": {
|
||||||
|
"editaccess": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"responsibilitycenter": "",
|
"responsibilitycenter": "",
|
||||||
@@ -1616,9 +1619,17 @@
|
|||||||
"signout": "desconectar",
|
"signout": "desconectar",
|
||||||
"updateprofile": "Actualización del perfil"
|
"updateprofile": "Actualización del perfil"
|
||||||
},
|
},
|
||||||
|
"errors": {
|
||||||
|
"updating": ""
|
||||||
|
},
|
||||||
"fields": {
|
"fields": {
|
||||||
|
"authlevel": "",
|
||||||
"displayname": "Nombre para mostrar",
|
"displayname": "Nombre para mostrar",
|
||||||
|
"email": "",
|
||||||
"photourl": "URL de avatar"
|
"photourl": "URL de avatar"
|
||||||
|
},
|
||||||
|
"labels": {
|
||||||
|
"actions": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"vehicles": {
|
"vehicles": {
|
||||||
|
|||||||
@@ -280,6 +280,9 @@
|
|||||||
"edit": "",
|
"edit": "",
|
||||||
"enter": "",
|
"enter": "",
|
||||||
"list": ""
|
"list": ""
|
||||||
|
},
|
||||||
|
"users": {
|
||||||
|
"editaccess": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"responsibilitycenter": "",
|
"responsibilitycenter": "",
|
||||||
@@ -1616,9 +1619,17 @@
|
|||||||
"signout": "Déconnexion",
|
"signout": "Déconnexion",
|
||||||
"updateprofile": "Mettre à jour le profil"
|
"updateprofile": "Mettre à jour le profil"
|
||||||
},
|
},
|
||||||
|
"errors": {
|
||||||
|
"updating": ""
|
||||||
|
},
|
||||||
"fields": {
|
"fields": {
|
||||||
|
"authlevel": "",
|
||||||
"displayname": "Afficher un nom",
|
"displayname": "Afficher un nom",
|
||||||
|
"email": "",
|
||||||
"photourl": "URL de l'avatar"
|
"photourl": "URL de l'avatar"
|
||||||
|
},
|
||||||
|
"labels": {
|
||||||
|
"actions": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"vehicles": {
|
"vehicles": {
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
- args:
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: associations
|
||||||
|
schema: public
|
||||||
|
type: drop_select_permission
|
||||||
|
- args:
|
||||||
|
permission:
|
||||||
|
allow_aggregations: false
|
||||||
|
columns:
|
||||||
|
- active
|
||||||
|
- authlevel
|
||||||
|
- id
|
||||||
|
- shopid
|
||||||
|
- useremail
|
||||||
|
computed_fields: []
|
||||||
|
filter:
|
||||||
|
user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: associations
|
||||||
|
schema: public
|
||||||
|
type: create_select_permission
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
- args:
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: associations
|
||||||
|
schema: public
|
||||||
|
type: drop_select_permission
|
||||||
|
- args:
|
||||||
|
permission:
|
||||||
|
allow_aggregations: false
|
||||||
|
columns:
|
||||||
|
- active
|
||||||
|
- authlevel
|
||||||
|
- id
|
||||||
|
- shopid
|
||||||
|
- useremail
|
||||||
|
computed_fields: []
|
||||||
|
filter:
|
||||||
|
bodyshop:
|
||||||
|
associations:
|
||||||
|
_and:
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: associations
|
||||||
|
schema: public
|
||||||
|
type: create_select_permission
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
- args:
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: associations
|
||||||
|
schema: public
|
||||||
|
type: drop_update_permission
|
||||||
|
- args:
|
||||||
|
permission:
|
||||||
|
columns:
|
||||||
|
- active
|
||||||
|
filter:
|
||||||
|
user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
set: {}
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: associations
|
||||||
|
schema: public
|
||||||
|
type: create_update_permission
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
- args:
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: associations
|
||||||
|
schema: public
|
||||||
|
type: drop_update_permission
|
||||||
|
- args:
|
||||||
|
permission:
|
||||||
|
columns:
|
||||||
|
- active
|
||||||
|
- authlevel
|
||||||
|
filter:
|
||||||
|
user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
set: {}
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: associations
|
||||||
|
schema: public
|
||||||
|
type: create_update_permission
|
||||||
@@ -204,14 +204,20 @@ tables:
|
|||||||
- shopid
|
- shopid
|
||||||
- useremail
|
- useremail
|
||||||
filter:
|
filter:
|
||||||
user:
|
bodyshop:
|
||||||
authid:
|
associations:
|
||||||
_eq: X-Hasura-User-Id
|
_and:
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
update_permissions:
|
update_permissions:
|
||||||
- role: user
|
- role: user
|
||||||
permission:
|
permission:
|
||||||
columns:
|
columns:
|
||||||
- active
|
- active
|
||||||
|
- authlevel
|
||||||
filter:
|
filter:
|
||||||
user:
|
user:
|
||||||
authid:
|
authid:
|
||||||
|
|||||||
Reference in New Issue
Block a user