Skip to content

Commit e801ed6

Browse files
committed
add more tracking
1 parent 07ca612 commit e801ed6

7 files changed

Lines changed: 314 additions & 202 deletions

File tree

OpenFlow/src/Auth.ts

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,24 @@
11
import { Crypt } from "./Crypt";
22
import { User } from "@openiap/openflow-api";
33
import { DBHelper } from "./DBHelper";
4+
import { otel } from "./otel";
5+
import { Span } from "@opentelemetry/api";
46
export class Auth {
5-
public static async ValidateByPassword(username: string, password: string): Promise<User> {
6-
if (username === null || username === undefined || username === "") { throw Error("Username cannot be null"); }
7-
if (password === null || password === undefined || password === "") { throw Error("Password cannot be null"); }
8-
const user: User = await DBHelper.FindByUsername(username);
9-
if (user === null || user === undefined) { return null; }
10-
if ((await Crypt.compare(password, user.passwordhash)) !== true) { return null; }
11-
return user;
7+
public static async ValidateByPassword(username: string, password: string, parent: Span): Promise<User> {
8+
const span: Span = otel.startSubSpan("Auth.ValidateByPassword", parent);
9+
try {
10+
if (username === null || username === undefined || username === "") { throw Error("Username cannot be null"); }
11+
span.setAttribute("username", username);
12+
if (password === null || password === undefined || password === "") { throw Error("Password cannot be null"); }
13+
const user: User = await DBHelper.FindByUsername(username, null, span);
14+
if (user === null || user === undefined) { return null; }
15+
if ((await Crypt.compare(password, user.passwordhash)) !== true) { return null; }
16+
return user;
17+
} catch (error) {
18+
span.recordException(error);
19+
throw error;
20+
} finally {
21+
otel.endSpan(span);
22+
}
1223
}
1324
}

OpenFlow/src/DBHelper.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import { otel } from "./otel";
55
import { Span } from "@opentelemetry/api";
66

77
export class DBHelper {
8-
public static async FindByUsername(username: string, jwt: string = null): Promise<User> {
8+
public static async FindByUsername(username: string, jwt: string = null, parent: Span): Promise<User> {
9+
const span: Span = otel.startSubSpan("dbhelper.EnsureRole", parent);
910
const byuser = { username: new RegExp(["^", username, "$"].join(""), "i") };
1011
const byid = { federationids: new RegExp(["^", username, "$"].join(""), "i") }
1112
const q = { $or: [byuser, byid] };

OpenFlow/src/DatabaseConnection.ts

Lines changed: 158 additions & 109 deletions
Large diffs are not rendered by default.

OpenFlow/src/LoginProvider.ts

Lines changed: 111 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -89,29 +89,41 @@ export class LoginProvider {
8989
}
9090

9191

92-
static async validateToken(rawAssertion: string): Promise<User> {
92+
static async validateToken(rawAssertion: string, parent: Span): Promise<User> {
93+
const span: Span = otel.startSubSpan("LoginProvider.validateToken", parent);
9394
return new Promise<User>((resolve, reject) => {
94-
const options = {
95-
publicKey: Buffer.from(Config.signing_crt, "base64").toString("ascii")
96-
}
97-
saml.validate(rawAssertion, options, async (err, profile) => {
98-
try {
99-
if (err) { return reject(err); }
100-
const claims = profile.claims; // Array of user attributes;
101-
const username = claims["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"] ||
102-
claims["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"] ||
103-
claims["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"];
104-
105-
const user = await DBHelper.FindByUsername(username);
106-
if (user) {
107-
resolve(user);
108-
} else {
109-
reject("Unknown user");
110-
}
111-
} catch (error) {
112-
reject(error);
95+
try {
96+
const options = {
97+
publicKey: Buffer.from(Config.signing_crt, "base64").toString("ascii")
11398
}
114-
});
99+
saml.validate(rawAssertion, options, async (err, profile) => {
100+
try {
101+
if (err) { span.recordException(err); return reject(err); }
102+
const claims = profile.claims; // Array of user attributes;
103+
const username = claims["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"] ||
104+
claims["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"] ||
105+
claims["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"];
106+
107+
const user = await DBHelper.FindByUsername(username, null, span);
108+
if (user) {
109+
resolve(user);
110+
} else {
111+
span.recordException("Unknown user");
112+
reject("Unknown user");
113+
}
114+
} catch (error) {
115+
span.recordException(error);
116+
reject(error);
117+
} finally {
118+
otel.endSpan(span);
119+
}
120+
121+
});
122+
} catch (error) {
123+
span.recordException(error);
124+
} finally {
125+
otel.endSpan(span);
126+
}
115127
});
116128
}
117129

@@ -211,65 +223,99 @@ export class LoginProvider {
211223
res.end();
212224
});
213225
app.get("/jwt", (req: any, res: any, next: any): void => {
214-
// logger.debug("/jwt " + !(req.user == null));
215-
res.setHeader("Content-Type", "application/json");
216-
if (req.user) {
217-
const user: TokenUser = TokenUser.From(req.user);
218-
res.end(JSON.stringify({ jwt: Crypt.createToken(user, Config.shorttoken_expires_in), user: user }));
219-
} else {
220-
res.end(JSON.stringify({ jwt: "" }));
226+
const span: Span = otel.startSpan("LoginProvider.jwtlong");
227+
try {
228+
res.setHeader("Content-Type", "application/json");
229+
if (req.user) {
230+
const user: TokenUser = TokenUser.From(req.user);
231+
span.setAttribute("username", user.username);
232+
res.end(JSON.stringify({ jwt: Crypt.createToken(user, Config.shorttoken_expires_in), user: user }));
233+
} else {
234+
res.end(JSON.stringify({ jwt: "" }));
235+
}
236+
res.end();
237+
} catch (error) {
238+
span.recordException(error);
239+
console.error(error.message ? error.message : error);
240+
return res.status(500).send({ message: error.message ? error.message : error });
241+
} finally {
242+
otel.endSpan(span);
221243
}
222-
res.end();
223244
});
224245
app.get("/jwtlong", (req: any, res: any, next: any): void => {
225-
// logger.debug("/jwtlong " + !(req.user == null));
226-
res.setHeader("Content-Type", "application/json");
227-
if (req.user) {
228-
const user: TokenUser = TokenUser.From(req.user);
229-
if (!(user.validated == true) && Config.validate_user_form != "") {
230-
res.end(JSON.stringify({ jwt: "" }));
246+
const span: Span = otel.startSpan("LoginProvider.jwtlong");
247+
try {
248+
res.setHeader("Content-Type", "application/json");
249+
if (req.user) {
250+
const user: TokenUser = TokenUser.From(req.user);
251+
span.setAttribute("username", user.username);
252+
if (!(user.validated == true) && Config.validate_user_form != "") {
253+
res.end(JSON.stringify({ jwt: "" }));
254+
} else {
255+
res.end(JSON.stringify({ jwt: Crypt.createToken(user, Config.longtoken_expires_in), user: user }));
256+
}
231257
} else {
232-
res.end(JSON.stringify({ jwt: Crypt.createToken(user, Config.longtoken_expires_in), user: user }));
258+
res.end(JSON.stringify({ jwt: "" }));
233259
}
234-
} else {
235-
res.end(JSON.stringify({ jwt: "" }));
260+
res.end();
261+
} catch (error) {
262+
span.recordException(error);
263+
console.error(error.message ? error.message : error);
264+
return res.status(500).send({ message: error.message ? error.message : error });
265+
} finally {
266+
otel.endSpan(span);
236267
}
237-
res.end();
238268
});
239269
app.post("/jwt", async (req: any, res: any, next: any): Promise<void> => {
270+
const span: Span = otel.startSpan("LoginProvider.jwt");
240271
// logger.debug("/jwt " + !(req.user == null));
241272
try {
242273
const rawAssertion = req.body.token;
243-
const user: User = await LoginProvider.validateToken(rawAssertion);
274+
const user: User = await LoginProvider.validateToken(rawAssertion, span);
244275
const tuser: TokenUser = TokenUser.From(user);
276+
span.setAttribute("username", user.username);
245277
res.setHeader("Content-Type", "application/json");
246278
res.end(JSON.stringify({ jwt: Crypt.createToken(tuser, Config.shorttoken_expires_in) }));
247279
} catch (error) {
280+
span.recordException(error);
248281
console.error(error.message ? error.message : error);
249282
return res.status(500).send({ message: error.message ? error.message : error });
283+
} finally {
284+
otel.endSpan(span);
250285
}
251286
});
252287
app.get("/config", (req: any, res: any, next: any): void => {
253-
let _url = Config.basewsurl();
254-
if (!NoderedUtil.IsNullEmpty(Config.api_ws_url)) _url = Config.api_ws_url;
255-
if (!_url.endsWith("/")) _url += "/";
256-
const res2 = {
257-
wshost: _url,
258-
wsurl: _url,
259-
domain: Config.domain,
260-
allow_user_registration: Config.allow_user_registration,
261-
allow_personal_nodered: Config.allow_personal_nodered,
262-
auto_create_personal_nodered_group: Config.auto_create_personal_nodered_group,
263-
namespace: Config.namespace,
264-
nodered_domain_schema: Config.nodered_domain_schema,
265-
websocket_package_size: Config.websocket_package_size,
266-
version: Config.version,
267-
stripe_api_key: Config.stripe_api_key,
268-
getting_started_url: Config.getting_started_url,
269-
validate_user_form: Config.validate_user_form,
270-
supports_watch: Config.supports_watch
271-
}
272-
res.end(JSON.stringify(res2));
288+
const span: Span = otel.startSpan("LoginProvider.config");
289+
try {
290+
let _url = Config.basewsurl();
291+
if (!NoderedUtil.IsNullEmpty(Config.api_ws_url)) _url = Config.api_ws_url;
292+
if (!_url.endsWith("/")) _url += "/";
293+
if (req.user) {
294+
const user: TokenUser = TokenUser.From(req.user);
295+
span.setAttribute("username", user.username);
296+
}
297+
const res2 = {
298+
wshost: _url,
299+
wsurl: _url,
300+
domain: Config.domain,
301+
allow_user_registration: Config.allow_user_registration,
302+
allow_personal_nodered: Config.allow_personal_nodered,
303+
auto_create_personal_nodered_group: Config.auto_create_personal_nodered_group,
304+
namespace: Config.namespace,
305+
nodered_domain_schema: Config.nodered_domain_schema,
306+
websocket_package_size: Config.websocket_package_size,
307+
version: Config.version,
308+
stripe_api_key: Config.stripe_api_key,
309+
getting_started_url: Config.getting_started_url,
310+
validate_user_form: Config.validate_user_form,
311+
supports_watch: Config.supports_watch
312+
}
313+
res.end(JSON.stringify(res2));
314+
} catch (error) {
315+
span.recordException(error);
316+
} finally {
317+
otel.endSpan(span);
318+
}
273319
});
274320
app.get("/login", async (req: any, res: any, next: any): Promise<void> => {
275321
// logger.debug("/login " + !(req.user == null));
@@ -666,12 +712,12 @@ export class LoginProvider {
666712

667713
static CreateLocalStrategy(app: express.Express, baseurl: string): passport.Strategy {
668714
const strategy: passport.Strategy = new LocalStrategy(async (username: string, password: string, done: any): Promise<void> => {
669-
const span: Span = otel.startSpan("LocalLogin");
715+
const span: Span = otel.startSpan("LoginProvider.LocalLogin");
670716
try {
671717
if (username !== null && username != undefined) { username = username.toLowerCase(); }
672718
let user: User = null;
673719
if (LoginProvider.login_providers.length === 0) {
674-
user = await DBHelper.FindByUsername(username);
720+
user = await DBHelper.FindByUsername(username, null, span);
675721
if (user == null) {
676722
user = new User(); user.name = username; user.username = username;
677723
await Crypt.SetPassword(user, password);
@@ -697,7 +743,7 @@ export class LoginProvider {
697743
const tuser: TokenUser = TokenUser.From(user);
698744
return done(null, tuser);
699745
}
700-
user = await DBHelper.FindByUsername(username);
746+
user = await DBHelper.FindByUsername(username, null, span);
701747
if (NoderedUtil.IsNullUndefinded(user)) {
702748
if (!Config.allow_user_registration) {
703749
return done(null, false);
@@ -792,7 +838,7 @@ export class LoginProvider {
792838
return strategy;
793839
}
794840
static async samlverify(profile: any, done: IVerifyFunction): Promise<void> {
795-
const span: Span = otel.startSpan("samlverify");
841+
const span: Span = otel.startSpan("LoginProvider.samlverify");
796842
try {
797843
let username: string = profile.username;
798844
if (NoderedUtil.IsNullEmpty(username)) username = profile.nameID;
@@ -866,7 +912,7 @@ export class LoginProvider {
866912
otel.endSpan(span);
867913
}
868914
static async googleverify(token: string, tokenSecret: string, profile: any, done: IVerifyFunction): Promise<void> {
869-
const span: Span = otel.startSpan("googleverify");
915+
const span: Span = otel.startSpan("LoginProvider.googleverify");
870916
try {
871917
if (profile.emails) {
872918
const email: any = profile.emails[0];

0 commit comments

Comments
 (0)