Skip to content

Commit ba15af9

Browse files
committed
Fixed issue with upgrading from 8.1 to 8.3
1 parent 5551fa5 commit ba15af9

7 files changed

Lines changed: 101 additions & 55 deletions

File tree

IgnitionNodeRED-gateway/src/main/java/org/imdc/nodered/GatewayHook.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44
import com.inductiveautomation.ignition.common.licensing.LicenseState;
55
import com.inductiveautomation.ignition.common.resourcecollection.ResourceType;
66
import com.inductiveautomation.ignition.gateway.config.ResourceTypeMeta;
7+
import com.inductiveautomation.ignition.gateway.config.migration.DefaultRecordEncodingDelegate;
78
import com.inductiveautomation.ignition.gateway.config.migration.IdbMigrationStrategy;
89
import com.inductiveautomation.ignition.gateway.config.migration.NamedRecordMigrationStrategy;
910
import com.inductiveautomation.ignition.gateway.model.AbstractGatewayModuleHook;
1011
import com.inductiveautomation.ignition.gateway.model.GatewayContext;
1112
import com.inductiveautomation.ignition.gateway.web.systemjs.SystemJsModule;
13+
import org.apache.commons.lang3.StringUtils;
1214
import org.imdc.nodered.servlet.NodeREDServlet;
1315
import org.imdc.nodered.servlet.NodeREDWebSocketServlet;
1416
import org.slf4j.Logger;
@@ -75,7 +77,7 @@ public void shutdown() {
7577

7678
@Override
7779
public List<IdbMigrationStrategy> getRecordMigrationStrategies() {
78-
return List.of(new NamedRecordMigrationStrategy(NodeREDAPITokens.META, TOKEN_RESOURCE_TYPE));
80+
return List.of(new NamedRecordMigrationStrategy(NodeREDAPITokens.META, NodeREDAPITokens.Name, null, NodeREDAPITokens.Enabled, TOKEN_RESOURCE_TYPE, new DefaultRecordEncodingDelegate()));
7981
}
8082

8183
@Override

IgnitionNodeRED-gateway/src/main/java/org/imdc/nodered/NodeREDAPITokenResource.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@
99
import java.nio.charset.StandardCharsets;
1010

1111
public record NodeREDAPITokenResource(
12-
@Description("16 character alphanumeric API token") String APIToken,
13-
@Description("The secret (password) paired with the API token") SecretConfig Secret,
14-
@Description("The name of the audit profile that tag write actions will log to") String AuditProfile,
15-
@Description("A comma separated list of security levels to impersonate. If specified, security levels take precedence over roles and zones.") String SecurityLevels,
16-
@Description("A comma separated list of roles to impersonate") String Roles,
17-
@Description("A comma separated list of zones to impersonate") String Zones) {
12+
@Description("16 character alphanumeric API token") String aPIToken,
13+
@Description("The secret (password) paired with the API token") SecretConfig secret,
14+
@Description("The name of the audit profile that tag write actions will log to") String auditProfile,
15+
@Description("A comma separated list of security levels to impersonate. If specified, security levels take precedence over roles and zones.") String securityLevels,
16+
@Description("A comma separated list of roles to impersonate") String roles,
17+
@Description("A comma separated list of zones to impersonate") String zones) {
1818

1919
public String getSecret(GatewayContext context) throws Exception {
20-
SecretConfig secretConfig = this.Secret();
20+
SecretConfig secretConfig = this.secret();
2121
if (secretConfig != null) {
2222
Secret<?> secret = com.inductiveautomation.ignition.gateway.secrets.Secret.create(context, secretConfig);
2323
Plaintext plaintext = secret.getPlaintext();

IgnitionNodeRED-gateway/src/main/java/org/imdc/nodered/servlet/APITokenValidation.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,13 @@ public static APITokenValidation validateToken(GatewayContext context, String ap
8383
ResourceCodec<NodeREDAPITokenResource> codec = GatewayHook.TOKEN_RESOURCE_TYPE_META.getCodec();
8484
DecodedResource<NodeREDAPITokenResource> decodedResource = codec.decode(resource);
8585
NodeREDAPITokenResource token = decodedResource.config();
86-
if (token.APIToken().equals(apiToken)) {
86+
if (token.aPIToken().equals(apiToken)) {
8787
if (decodedResource.enabled()) {
8888
if (!token.getSecret(context).equals(secret)) {
8989
success = false;
9090
errorMessage = "Invalid API token and secret";
9191
} else {
92-
return new APITokenValidation(success, errorMessage, decodedResource.name(), token.APIToken(), token.AuditProfile(), token.SecurityLevels(), token.Roles(), token.Zones());
92+
return new APITokenValidation(success, errorMessage, decodedResource.name(), token.aPIToken(), token.auditProfile(), token.securityLevels(), token.roles(), token.zones());
9393
}
9494
} else {
9595
success = false;

IgnitionNodeRED-web/src/pages/Tokens/TokenAddModal.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const TokenAddModal = ({
2323
isDisabled,
2424
}: TokenAddModalProps) => {
2525
const {
26-
classes: { scModalTitle, scModal, scFormRoot, scModalFooter, scForm },
26+
classes: { scModalTitle, scModal, scFormRoot, scModalFooter, scForm500 },
2727
} = getNodeREDPageStyles();
2828

2929
const {
@@ -45,7 +45,7 @@ const TokenAddModal = ({
4545
</button>
4646
</div>
4747
<div className={scModal}>
48-
<div className={scForm}>
48+
<div className={scForm500}>
4949
<Form
5050
onSubmit={create}
5151
context={context}

IgnitionNodeRED-web/src/pages/Tokens/TokenForm.tsx

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ import {
55
Checkbox,
66
TextArea,
77
TextInput,
8+
SelectInput,
9+
SelectInputOption,
810
} from "@inductiveautomation/ignition-web-ui";
11+
import useFetch from "../../utils/useFetch";
912
import { getNodeREDPageStyles } from "../_NodeRED.styles";
1013

1114
const TokenForm = ({ isEdit }: { isEdit: boolean }) => {
@@ -15,6 +18,23 @@ const TokenForm = ({ isEdit }: { isEdit: boolean }) => {
1518
classes: { scDrawerCard },
1619
} = getNodeREDPageStyles();
1720

21+
const { data: auditProfiles } = useFetch(
22+
`/data/api/v1/resources/names/ignition/audit-profile`,
23+
{
24+
headers: {
25+
Accept: "application/json",
26+
"Content-Type": "application/json",
27+
},
28+
}
29+
);
30+
31+
const auditProfileOptions: SelectInputOption[] =
32+
auditProfiles?.items
33+
?.map((item: { name: string }) => {
34+
return { value: item.name, label: item.name };
35+
})
36+
.filter((item: any) => item) ?? [];
37+
1838
return (
1939
<div>
2040
<Card title={"GENERAL"} className={scDrawerCard} required={true}>
@@ -44,7 +64,7 @@ const TokenForm = ({ isEdit }: { isEdit: boolean }) => {
4464
<Card title={"TOKEN CONFIGURATION"} required={true}>
4565
<FormControlInput
4666
input={<TextArea />}
47-
name={"config.APIToken"}
67+
name={"config.aPIToken"}
4868
id={"token"}
4969
label={"Token *"}
5070
/>
@@ -67,7 +87,7 @@ const TokenForm = ({ isEdit }: { isEdit: boolean }) => {
6787
disabled={!secretEnabled}
6888
indent={true}
6989
input={<TextInput type={"password"} />}
70-
name={"config.Secret"}
90+
name={"config.secret"}
7191
id={"secret"}
7292
label={"Secret"}
7393
/>
@@ -86,7 +106,7 @@ const TokenForm = ({ isEdit }: { isEdit: boolean }) => {
86106
<>
87107
<FormControlInput
88108
input={<TextInput type={"password"} />}
89-
name={"config.Secret"}
109+
name={"config.secret"}
90110
id={"secret"}
91111
label={"Secret *"}
92112
/>
@@ -99,6 +119,30 @@ const TokenForm = ({ isEdit }: { isEdit: boolean }) => {
99119
/>
100120
</>
101121
)}
122+
<FormControlInput
123+
input={<SelectInput values={auditProfileOptions} />}
124+
name={"config.auditProfile"}
125+
id={"auditProfile"}
126+
label={"Audit Profile"}
127+
/>
128+
<FormControlInput
129+
input={<TextInput />}
130+
name={"config.securityLevels"}
131+
id={"securityLevels"}
132+
label={"Security Levels"}
133+
/>
134+
<FormControlInput
135+
input={<TextInput />}
136+
name={"config.roles"}
137+
id={"roles"}
138+
label={"Roles"}
139+
/>
140+
<FormControlInput
141+
input={<TextInput />}
142+
name={"config.zones"}
143+
id={"zones"}
144+
label={"Zones"}
145+
/>
102146
</Card>
103147
</div>
104148
);

IgnitionNodeRED-web/src/pages/Tokens/TokenForm.types.ts

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ import { yup } from "@inductiveautomation/ignition-web-ui";
22
import { FieldValues } from "react-hook-form";
33

44
export interface TokenConfig {
5-
APIToken: string;
6-
Secret: string;
5+
aPIToken: string;
6+
secret: string;
77
storedSecret: any;
8-
AuditProfile: string;
9-
SecurityLevels: string;
10-
Roles: string;
11-
Zones: string;
8+
auditProfile: string;
9+
securityLevels: string;
10+
roles: string;
11+
zones: string;
1212
}
1313

1414
export interface TokenResource {
@@ -26,18 +26,18 @@ export namespace TokenUtils {
2626
description: yup.string(),
2727
signature: yup.string().nullable(),
2828
config: yup.object().shape({
29-
APIToken: yup
29+
aPIToken: yup
3030
.string()
3131
.required("Token is required")
3232
.length(16, "Must be exactly 16 characters")
3333
.matches(/^[a-zA-Z0-9]+$/, "Must contain only alphanumeric characters"),
34-
Secret: yup.string().required("Secret is required"),
34+
secret: yup.string().required("Secret is required"),
3535
changeSecret: yup.boolean(),
3636
confirmSecret: yup.string(),
37-
AuditProfile: yup.string().nullable(),
38-
SecurityLevels: yup.string(),
39-
Roles: yup.string(),
40-
Zones: yup.string(),
37+
auditProfile: yup.string().nullable(),
38+
securityLevels: yup.string(),
39+
roles: yup.string(),
40+
zones: yup.string(),
4141
}),
4242
});
4343

@@ -47,14 +47,14 @@ export namespace TokenUtils {
4747
signature: null,
4848
description: "",
4949
config: {
50-
APIToken: "",
51-
Secret: "",
50+
aPIToken: "",
51+
secret: "",
5252
changeSecret: false,
5353
confirmSecret: "",
54-
AuditProfile: null,
55-
SecurityLevels: "",
56-
Roles: "",
57-
Zones: "",
54+
auditProfile: null,
55+
securityLevels: "",
56+
roles: "",
57+
zones: "",
5858
},
5959
};
6060
}

IgnitionNodeRED-web/src/pages/Tokens/TokensPage.tsx

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ const TokensPage = () => {
109109
resolver: yupResolver(TokenSchema),
110110
});
111111

112-
const secret = context.watch("config.Secret");
112+
const secret = context.watch("config.secret");
113113
const confirmSecret = context.watch("config.confirmSecret");
114114
const changeSecret = context.watch("config.changeSecret");
115115

@@ -147,12 +147,12 @@ const TokensPage = () => {
147147
signature: data.signature,
148148
description: data.description,
149149
config: {
150-
APIToken: data.config.APIToken,
151-
storedSecret: data.config.Secret,
152-
AuditProfile: data.config.AuditProfile,
153-
SecurityLevels: data.config.SecurityLevels,
154-
Roles: data.config.Roles,
155-
Zones: data.config.Zones,
150+
aPIToken: data.config.aPIToken,
151+
storedSecret: data.config.secret,
152+
auditProfile: data.config.auditProfile,
153+
securityLevels: data.config.securityLevels,
154+
roles: data.config.roles,
155+
zones: data.config.zones,
156156
},
157157
} as TokenResource);
158158
setEditDrawer(true);
@@ -232,7 +232,7 @@ const TokensPage = () => {
232232
"Content-Type": "application/json",
233233
"X-CSRF-Token": csrfToken,
234234
},
235-
body: formValues.config.Secret,
235+
body: formValues.config.secret,
236236
}
237237
);
238238

@@ -266,12 +266,12 @@ const TokensPage = () => {
266266
enabled: formValues.enabled,
267267
description: formValues.description,
268268
config: {
269-
APIToken: formValues.config.APIToken,
270-
Secret: { ...encryptedSecret },
271-
AuditProfile: formValues.config.AuditProfile,
272-
SecurityLevels: formValues.config.SecurityLevels,
273-
Roles: formValues.config.Roles,
274-
Zones: formValues.config.Zones,
269+
aPIToken: formValues.config.aPIToken,
270+
secret: { ...encryptedSecret },
271+
auditProfile: formValues.config.auditProfile,
272+
securityLevels: formValues.config.securityLevels,
273+
roles: formValues.config.roles,
274+
zones: formValues.config.zones,
275275
},
276276
},
277277
]),
@@ -303,7 +303,7 @@ const TokensPage = () => {
303303
let encryptedSecret: { type: string; data: {} } | null;
304304
encryptedSecret = null;
305305

306-
if (formValues.config.Secret && formValues.config.Secret != "") {
306+
if (formValues.config.secret && formValues.config.secret != "") {
307307
const encryptSecretResponse = await fetch(
308308
"/data/api/v1/encryption/encrypt",
309309
{
@@ -312,7 +312,7 @@ const TokensPage = () => {
312312
"Content-Type": "application/json",
313313
"X-CSRF-Token": csrfToken,
314314
},
315-
body: formValues.config.Secret,
315+
body: formValues.config.secret,
316316
}
317317
);
318318

@@ -349,14 +349,14 @@ const TokensPage = () => {
349349
enabled: formValues.enabled,
350350
description: formValues.description,
351351
config: {
352-
APIToken: formValues.config.APIToken,
353-
Secret: encryptedSecret
352+
aPIToken: formValues.config.aPIToken,
353+
secret: encryptedSecret
354354
? { ...encryptedSecret }
355355
: tokenResource.config.storedSecret,
356-
AuditProfile: formValues.config.AuditProfile,
357-
SecurityLevels: formValues.config.SecurityLevels,
358-
Roles: formValues.config.Roles,
359-
Zones: formValues.config.Zones,
356+
auditProfile: formValues.config.auditProfile,
357+
securityLevels: formValues.config.securityLevels,
358+
roles: formValues.config.roles,
359+
zones: formValues.config.zones,
360360
},
361361
},
362362
]),

0 commit comments

Comments
 (0)