Skip to content

Commit 5a763ef

Browse files
committed
Add personal apiuser role
1 parent d44e147 commit 5a763ef

8 files changed

Lines changed: 49 additions & 72 deletions

File tree

OpenFlow/src/Config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export class Config {
4141
Config.persist_user_impersonation = Config.parseBoolean(Config.getEnv("persist_user_impersonation", "true"));
4242
Config.allow_personal_nodered = Config.parseBoolean(Config.getEnv("allow_personal_nodered", "false"));
4343
Config.auto_create_personal_nodered_group = Config.parseBoolean(Config.getEnv("auto_create_personal_nodered_group", "false"));
44+
Config.auto_create_personal_noderedapi_group = Config.parseBoolean(Config.getEnv("auto_create_personal_noderedapi_group", "false"));
4445
Config.force_add_admins = Config.parseBoolean(Config.getEnv("force_add_admins", "true"));
4546

4647
Config.tls_crt = Config.getEnv("tls_crt", "");
@@ -163,6 +164,7 @@ export class Config {
163164
public static allow_personal_nodered: boolean = Config.parseBoolean(Config.getEnv("allow_personal_nodered", "false"));
164165
public static use_ingress_beta1_syntax: boolean = Config.parseBoolean(Config.getEnv("use_ingress_beta1_syntax", "true"));
165166
public static auto_create_personal_nodered_group: boolean = Config.parseBoolean(Config.getEnv("auto_create_personal_nodered_group", "false"));
167+
public static auto_create_personal_noderedapi_group: boolean = Config.parseBoolean(Config.getEnv("auto_create_personal_noderedapi_group", "false"));
166168
public static force_add_admins: boolean = Config.parseBoolean(Config.getEnv("force_add_admins", "true"));
167169

168170
public static tls_crt: string = Config.getEnv("tls_crt", "");

OpenFlow/src/DBHelper.ts

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -227,19 +227,7 @@ export class DBHelper {
227227
await this.Save(user, jwt, span);
228228
const users: Role = await this.FindRoleByName("users", span);
229229
users.AddMember(user);
230-
231-
if (Config.auto_create_personal_nodered_group) {
232-
let name = user.username;
233-
name = name.split("@").join("").split(".").join("");
234-
name = name.toLowerCase();
235-
236-
const noderedadmins = await this.EnsureRole(jwt, name + "noderedadmins", null, span);
237-
Base.addRight(noderedadmins, user._id, user.username, [Rights.full_control]);
238-
Base.removeRight(noderedadmins, user._id, [Rights.delete]);
239-
noderedadmins.AddMember(user);
240-
await this.Save(noderedadmins, jwt, span);
241-
}
242-
230+
this.EnsureNoderedRoles(user, jwt, span);
243231
await this.Save(users, jwt, span)
244232
await this.DecorateWithRoles(user, span);
245233
return user;
@@ -250,5 +238,28 @@ export class DBHelper {
250238
Logger.otel.endSpan(span);
251239
}
252240
}
241+
public static async EnsureNoderedRoles(user: TokenUser | User, jwt: string, parent: Span): Promise<void> {
242+
if (Config.auto_create_personal_nodered_group) {
243+
let name = user.username;
244+
name = name.split("@").join("").split(".").join("");
245+
name = name.toLowerCase();
253246

247+
const noderedadmins = await this.EnsureRole(jwt, name + "noderedadmins", null, parent);
248+
Base.addRight(noderedadmins, user._id, user.username, [Rights.full_control]);
249+
Base.removeRight(noderedadmins, user._id, [Rights.delete]);
250+
noderedadmins.AddMember(user as User);
251+
await this.Save(noderedadmins, jwt, parent);
252+
}
253+
if (Config.auto_create_personal_noderedapi_group) {
254+
let name = user.username;
255+
name = name.split("@").join("").split(".").join("");
256+
name = name.toLowerCase();
257+
258+
const noderedadmins = await this.EnsureRole(jwt, name + "nodered api users", null, parent);
259+
Base.addRight(noderedadmins, user._id, user.username, [Rights.full_control]);
260+
Base.removeRight(noderedadmins, user._id, [Rights.delete]);
261+
noderedadmins.AddMember(user as User);
262+
await this.Save(noderedadmins, jwt, parent);
263+
}
264+
}
254265
}

OpenFlow/src/DatabaseConnection.ts

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -935,20 +935,7 @@ export class DatabaseConnection {
935935
span.addEvent("Save");
936936
await DBHelper.Save(users, Crypt.rootToken(), span);
937937
const user2: TokenUser = item as any;
938-
if (Config.auto_create_personal_nodered_group) {
939-
let name = user2.username;
940-
name = name.split("@").join("").split(".").join("");
941-
name = name.toLowerCase();
942-
943-
span.addEvent("EnsureRole");
944-
const noderedadmins = await DBHelper.EnsureRole(jwt, name + "noderedadmins", null, span);
945-
Base.addRight(noderedadmins, user2._id, user2.username, [Rights.full_control]);
946-
Base.removeRight(noderedadmins, user2._id, [Rights.delete]);
947-
noderedadmins.AddMember(item);
948-
span.addEvent("Save");
949-
await DBHelper.Save(noderedadmins, Crypt.rootToken(), span);
950-
}
951-
938+
DBHelper.EnsureNoderedRoles(user2, Crypt.rootToken(), span);
952939
}
953940
if (collectionname === "users" && item._type === "role") {
954941
Base.addRight(item, item._id, item.name, [Rights.read]);

OpenFlow/src/LoginProvider.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,7 @@ export class LoginProvider {
412412
auto_create_users: Config.auto_create_users,
413413
allow_personal_nodered: Config.allow_personal_nodered,
414414
auto_create_personal_nodered_group: Config.auto_create_personal_nodered_group,
415+
auto_create_personal_noderedapi_group: Config.auto_create_personal_noderedapi_group,
415416
namespace: Config.namespace,
416417
nodered_domain_schema: nodered_domain_schema,
417418
websocket_package_size: Config.websocket_package_size,

OpenFlow/src/Messages/Message.ts

Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,14 +1195,7 @@ export class Message {
11951195
name = name.split("@").join("").split(".").join("");
11961196
name = name.toLowerCase();
11971197

1198-
Logger.instanse.debug("[" + user.username + "] ensure nodered role " + name + "noderedadmins");
1199-
const noderedadmins = await DBHelper.EnsureRole(jwt, name + "noderedadmins", null, span);
1200-
Base.addRight(noderedadmins, user._id, user.username, [Rights.full_control]);
1201-
Base.removeRight(noderedadmins, user._id, [Rights.delete]);
1202-
noderedadmins.AddMember(user);
1203-
Logger.instanse.debug("[" + user.username + "] update nodered role " + name + "noderedadmins");
1204-
await DBHelper.Save(noderedadmins, jwt, span);
1205-
1198+
DBHelper.EnsureNoderedRoles(user, jwt, span);
12061199
} catch (error) {
12071200
span.recordException(error);
12081201
if (NoderedUtil.IsNullUndefinded(msg)) { (msg as any) = {}; }
@@ -1390,19 +1383,8 @@ export class Message {
13901383
const tuser: TokenUser = TokenUser.From(nodereduser);
13911384
const nodered_jwt: string = Crypt.createToken(tuser, Config.personalnoderedtoken_expires_in);
13921385

1393-
Logger.instanse.debug("[" + cli.user.username + "] ensure nodered role " + name + "noderedadmins");
1394-
const noderedadmins = await DBHelper.EnsureRole(cli.jwt, name + "noderedadmins", null, span);
1395-
Base.addRight(noderedadmins, nodereduser._id, nodereduser.username, [Rights.full_control]);
1396-
Base.removeRight(noderedadmins, nodereduser._id, [Rights.delete]);
1397-
Base.addRight(noderedadmins, cli.user._id, cli.user.username, [Rights.full_control]);
1398-
Base.removeRight(noderedadmins, cli.user._id, [Rights.delete]);
1399-
noderedadmins.AddMember(nodereduser);
1400-
Logger.instanse.debug("[" + cli.user.username + "] update nodered role " + name + "noderedadmins");
1401-
await DBHelper.Save(noderedadmins, cli.jwt, span);
1402-
1403-
1386+
DBHelper.EnsureNoderedRoles(tuser, cli.jwt, span);
14041387
let saml_baseurl = Config.protocol + "://" + hostname + "/";
1405-
14061388
let _samlparsed = url.parse(Config.saml_federation_metadata);
14071389
if (_samlparsed.protocol == "http:" || _samlparsed.protocol == "ws:") {
14081390
saml_baseurl = "http://" + hostname
@@ -1416,10 +1398,7 @@ export class Message {
14161398
}
14171399
}
14181400
saml_baseurl += "/";
1419-
1420-
14211401
// "saml_baseurl=" + saml_baseurl,
1422-
14231402
const Env = [
14241403
"saml_federation_metadata=" + Config.saml_federation_metadata,
14251404
"saml_issuer=" + Config.saml_issuer,
@@ -1435,6 +1414,7 @@ export class Message {
14351414
"port=" + Config.port.toString(),
14361415
"noderedusers=" + (name + "noderedusers"),
14371416
"noderedadmins=" + (name + "noderedadmins"),
1417+
"noderedapiusers=" + (name + "nodered api users"),
14381418
"api_allow_anonymous=" + user.nodered.api_allow_anonymous.toString(),
14391419
"function_external_modules=" + user.nodered.function_external_modules.toString(),
14401420
"prometheus_measure_nodeid=" + Config.prometheus_measure_nodeid.toString(),
@@ -1527,15 +1507,7 @@ export class Message {
15271507
const tuser: TokenUser = TokenUser.From(nodereduser);
15281508
const nodered_jwt: string = Crypt.createToken(tuser, Config.personalnoderedtoken_expires_in);
15291509

1530-
Logger.instanse.debug("[" + cli.user.username + "] ensure nodered role " + name + "noderedadmins");
1531-
const noderedadmins = await DBHelper.EnsureRole(cli.jwt, name + "noderedadmins", null, span);
1532-
Base.addRight(noderedadmins, nodereduser._id, nodereduser.username, [Rights.full_control]);
1533-
Base.removeRight(noderedadmins, nodereduser._id, [Rights.delete]);
1534-
Base.addRight(noderedadmins, cli.user._id, cli.user.username, [Rights.full_control]);
1535-
Base.removeRight(noderedadmins, cli.user._id, [Rights.delete]);
1536-
noderedadmins.AddMember(nodereduser);
1537-
Logger.instanse.debug("[" + cli.user.username + "] update nodered role " + name + "noderedadmins");
1538-
await DBHelper.Save(noderedadmins, cli.jwt, span);
1510+
DBHelper.EnsureNoderedRoles(tuser, cli.jwt, span);
15391511

15401512
const resources = new V1ResourceRequirements();
15411513
let hasbilling: boolean = false;
@@ -1694,6 +1666,7 @@ export class Message {
16941666
{ name: "port", value: Config.port.toString() },
16951667
{ name: "noderedusers", value: (name + "noderedusers") },
16961668
{ name: "noderedadmins", value: (name + "noderedadmins") },
1669+
{ name: "noderedapiusers", value: (name + "nodered api users") },
16971670
{ name: "api_allow_anonymous", value: user.nodered.api_allow_anonymous.toString() },
16981671
{ name: "function_external_modules", value: user.nodered.function_external_modules.toString() },
16991672
{ name: "prometheus_measure_nodeid", value: Config.prometheus_measure_nodeid.toString() },

OpenFlow/src/public/Controllers.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1087,12 +1087,12 @@ export class UsersCtrl extends entitiesCtrl<TokenUser> {
10871087
name = name.split("@").join("").split(".").join("");
10881088
name = name.toLowerCase();
10891089

1090-
const list = await NoderedUtil.Query("users", { _type: "role", name: name + "noderedadmins" }, null, null, 2, 0, null);
1091-
if (list.length == 1) {
1092-
console.debug("Deleting " + name + "noderedadmins")
1093-
await NoderedUtil.DeleteOne("users", list[0]._id, null);
1090+
var q = { _type: "role", "$or": [{ name: name + "noderedadmins" }, { name: name + "nodered api users" }] }
1091+
const list = await NoderedUtil.Query("users", q, null, null, 4, 0, null);
1092+
for (var i = 0; i < list.length; i++) {
1093+
console.debug("Deleting " + list[i].name)
1094+
await NoderedUtil.DeleteOne("users", list[i]._id, null);
10941095
}
1095-
10961096
if (!this.$scope.$$phase) { this.$scope.$apply(); }
10971097
}
10981098
}
@@ -3961,10 +3961,11 @@ export class CredentialsCtrl extends entitiesCtrl<Base> {
39613961
name = name.split("@").join("").split(".").join("");
39623962
name = name.toLowerCase();
39633963

3964-
const list = await NoderedUtil.Query("users", { _type: "role", name: name + "noderedadmins" }, null, null, 2, 0, null);
3965-
if (list.length == 1) {
3966-
console.debug("Deleting " + name + "noderedadmins")
3967-
await NoderedUtil.DeleteOne("users", list[0]._id, null);
3964+
var q = { _type: "role", "$or": [{ name: name + "noderedadmins" }, { name: name + "nodered api users" }] }
3965+
const list = await NoderedUtil.Query("users", q, null, null, 4, 0, null);
3966+
for (var i = 0; i < list.length; i++) {
3967+
console.debug("Deleting " + list[i].name)
3968+
await NoderedUtil.DeleteOne("users", list[i]._id, null);
39683969
}
39693970

39703971
if (!this.$scope.$$phase) { this.$scope.$apply(); }

OpenFlowNodeRED/src/Config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export class Config {
3737
Config.protocol = Config.getEnv("protocol", "http");
3838
Config.noderedusers = Config.getEnv("noderedusers", "");
3939
Config.noderedadmins = Config.getEnv("noderedadmins", "");
40+
Config.noderedapiusers = Config.getEnv("noderedapiusers", "");
4041
Config.cookie_secret = Config.getEnv("cookie_secret", "NLgUIsozJaxO38ze0WuHthfj2eb1eIEu");
4142

4243
Config.flow_refresh_interval = parseInt(Config.getEnv("flow_refresh_interval", "60000"));
@@ -101,6 +102,7 @@ export class Config {
101102
public static protocol: string = Config.getEnv("protocol", "http");
102103
public static noderedusers: string = Config.getEnv("noderedusers", "");
103104
public static noderedadmins: string = Config.getEnv("noderedadmins", "");
105+
public static noderedapiusers: string = Config.getEnv("noderedapiusers", "");
104106
public static cookie_secret: string = Config.getEnv("cookie_secret", "NLgUIsozJaxO38ze0WuHthfj2eb1eIEu"); // Used to protect cookies
105107

106108
public static flow_refresh_interval: number = parseInt(Config.getEnv("flow_refresh_interval", "60000"));

OpenFlowNodeRED/src/node-red-contrib-middleware-auth.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ export class noderedcontribmiddlewareauth {
4949
if (result == null || result.user == null) result = await NoderedUtil.SigninWithToken(null, token, null, false, true);
5050
if (result.user != null) {
5151
const user: TokenUser = TokenUser.assign(result.user);
52-
const allowed = user.roles.filter(x => x.name == "nodered api users" || x.name == Config.noderedadmins);
53-
if (allowed.length > 0) {
52+
const allowed = user.roles.filter(x => x.name == "nodered api users" || x.name == Config.noderedadmins || x.name == Config.noderedapiusers);
53+
if (allowed.length > 0 && !NoderedUtil.IsNullEmpty(allowed[0].name)) {
5454
cacheduser = new CachedUser(result.user, result.jwt);
5555
this.authorizationCache[authorization] = cacheduser;
5656
Logger.instanse.info("noderedcontribmiddlewareauth: Authorized " + user.username + " for " + req.url);
@@ -79,8 +79,8 @@ export class noderedcontribmiddlewareauth {
7979
const result = await NoderedUtil.SigninWithUsername(login, password, null, false, true);
8080
if (result.user != null) {
8181
const user: TokenUser = TokenUser.assign(result.user);
82-
const allowed = user.roles.filter(x => x.name == "nodered api users" || x.name == Config.noderedadmins);
83-
if (allowed.length > 0) {
82+
const allowed = user.roles.filter(x => x.name == "nodered api users" || x.name == Config.noderedadmins || x.name == Config.noderedapiusers);
83+
if (allowed.length > 0 && !NoderedUtil.IsNullEmpty(allowed[0].name)) {
8484
cacheduser = new CachedUser(result.user, result.jwt);
8585
this.authorizationCache[authorization] = cacheduser;
8686
Logger.instanse.info("noderedcontribmiddlewareauth: Authorized " + user.username + " for " + req.url);

0 commit comments

Comments
 (0)