mirror of
https://github.com/wassname/talk.git
synced 2026-08-19 12:40:16 +08:00
feat: added allowRegistration option
This commit is contained in:
@@ -136,13 +136,10 @@ export const OIDCIDTokenSchema = Joi.object()
|
||||
email: Joi.string(),
|
||||
email_verified: Joi.boolean().default(false),
|
||||
picture: Joi.string().default(undefined),
|
||||
name: Joi.string().default(undefined),
|
||||
nickname: Joi.string().default(undefined),
|
||||
})
|
||||
.optionalKeys(["picture", "email_verified"]);
|
||||
|
||||
export const OIDCDisplayNameIDTokenSchema = OIDCIDTokenSchema.keys({
|
||||
name: Joi.string().default(undefined),
|
||||
nickname: Joi.string().default(undefined),
|
||||
}).optionalKeys(["name", "nickname"]);
|
||||
.optionalKeys(["picture", "email_verified", "name", "nickname"]);
|
||||
|
||||
export async function findOrCreateOIDCUser(
|
||||
db: Db,
|
||||
@@ -160,12 +157,7 @@ export async function findOrCreateOIDCUser(
|
||||
picture,
|
||||
name,
|
||||
nickname,
|
||||
}: OIDCIDToken = validate(
|
||||
integration.displayNameEnable
|
||||
? OIDCDisplayNameIDTokenSchema
|
||||
: OIDCIDTokenSchema,
|
||||
token
|
||||
);
|
||||
}: OIDCIDToken = validate(OIDCIDTokenSchema, token);
|
||||
|
||||
// Construct the profile that will be used to query for the user.
|
||||
const profile: OIDCProfile = {
|
||||
@@ -178,10 +170,13 @@ export async function findOrCreateOIDCUser(
|
||||
// Try to lookup user given their id provided in the `sub` claim.
|
||||
let user = await retrieveUserWithProfile(db, tenant.id, profile);
|
||||
if (!user) {
|
||||
if (!integration.allowRegistration) {
|
||||
// Registration is disabled, so we can't create the user user here.
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: implement rules.
|
||||
|
||||
// Default the displayName. When it is disabled, Joi will strip the
|
||||
// displayName fields from the token, so it will fallback to undefined.
|
||||
const displayName = nickname || name || undefined;
|
||||
|
||||
// Create the new user, as one didn't exist before!
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import {
|
||||
OIDCDisplayNameIDTokenSchema,
|
||||
OIDCIDTokenSchema,
|
||||
} from "talk-server/app/middleware/passport/strategies/oidc";
|
||||
import { OIDCIDTokenSchema } from "talk-server/app/middleware/passport/strategies/oidc";
|
||||
import { validate } from "talk-server/app/request/body";
|
||||
|
||||
describe("OIDCIDTokenSchema", () => {
|
||||
@@ -42,9 +39,7 @@ describe("OIDCIDTokenSchema", () => {
|
||||
|
||||
expect(validate(OIDCIDTokenSchema, token)).toEqual(token);
|
||||
});
|
||||
});
|
||||
|
||||
describe("OIDCDisplayNameIDTokenSchema", () => {
|
||||
it("allows a valid payload", () => {
|
||||
const token = {
|
||||
sub: "sub",
|
||||
@@ -56,7 +51,7 @@ describe("OIDCDisplayNameIDTokenSchema", () => {
|
||||
nickname: "nickname",
|
||||
};
|
||||
|
||||
expect(validate(OIDCDisplayNameIDTokenSchema, token)).toEqual(token);
|
||||
expect(validate(OIDCIDTokenSchema, token)).toEqual(token);
|
||||
});
|
||||
|
||||
it("allows an empty name", () => {
|
||||
@@ -69,7 +64,7 @@ describe("OIDCDisplayNameIDTokenSchema", () => {
|
||||
nickname: "nickname",
|
||||
};
|
||||
|
||||
expect(validate(OIDCDisplayNameIDTokenSchema, token)).toEqual(token);
|
||||
expect(validate(OIDCIDTokenSchema, token)).toEqual(token);
|
||||
});
|
||||
|
||||
it("allows an empty nickname", () => {
|
||||
@@ -82,6 +77,6 @@ describe("OIDCDisplayNameIDTokenSchema", () => {
|
||||
name: "name",
|
||||
};
|
||||
|
||||
expect(validate(OIDCDisplayNameIDTokenSchema, token)).toEqual(token);
|
||||
expect(validate(OIDCIDTokenSchema, token)).toEqual(token);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import {
|
||||
isSSOToken,
|
||||
SSODisplayNameUserProfileSchema,
|
||||
SSOUserProfileSchema,
|
||||
} from "talk-server/app/middleware/passport/strategies/verifiers/sso";
|
||||
import { validate } from "talk-server/app/request/body";
|
||||
@@ -44,9 +43,7 @@ describe("SSOUserProfileSchema", () => {
|
||||
|
||||
expect(validate(SSOUserProfileSchema, profile)).toEqual(profile);
|
||||
});
|
||||
});
|
||||
|
||||
describe("SSODisplayNameUserProfileSchema", () => {
|
||||
it("allows a valid payload", () => {
|
||||
const profile = {
|
||||
id: "id",
|
||||
@@ -56,7 +53,7 @@ describe("SSODisplayNameUserProfileSchema", () => {
|
||||
displayName: "displayName",
|
||||
};
|
||||
|
||||
expect(validate(SSODisplayNameUserProfileSchema, profile)).toEqual(profile);
|
||||
expect(validate(SSOUserProfileSchema, profile)).toEqual(profile);
|
||||
});
|
||||
|
||||
it("allows an empty avatar", () => {
|
||||
@@ -67,7 +64,7 @@ describe("SSODisplayNameUserProfileSchema", () => {
|
||||
displayName: "displayName",
|
||||
};
|
||||
|
||||
expect(validate(SSODisplayNameUserProfileSchema, profile)).toEqual(profile);
|
||||
expect(validate(SSOUserProfileSchema, profile)).toEqual(profile);
|
||||
});
|
||||
|
||||
it("allows an empty displayName", () => {
|
||||
@@ -78,6 +75,6 @@ describe("SSODisplayNameUserProfileSchema", () => {
|
||||
avatar: "avatar",
|
||||
};
|
||||
|
||||
expect(validate(SSODisplayNameUserProfileSchema, profile)).toEqual(profile);
|
||||
expect(validate(SSOUserProfileSchema, profile)).toEqual(profile);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,7 +3,10 @@ import jwt from "jsonwebtoken";
|
||||
import { Db } from "mongodb";
|
||||
|
||||
import { validate } from "talk-server/app/request/body";
|
||||
import { GQLUSER_ROLE } from "talk-server/graph/tenant/schema/__generated__/types";
|
||||
import {
|
||||
GQLSSOAuthIntegration,
|
||||
GQLUSER_ROLE,
|
||||
} from "talk-server/graph/tenant/schema/__generated__/types";
|
||||
import { Tenant } from "talk-server/models/tenant";
|
||||
import { retrieveUserWithProfile, SSOProfile } from "talk-server/models/user";
|
||||
import { upsert } from "talk-server/services/users";
|
||||
@@ -30,16 +33,14 @@ export const SSOUserProfileSchema = Joi.object()
|
||||
email: Joi.string(),
|
||||
username: Joi.string(),
|
||||
avatar: Joi.string().default(undefined),
|
||||
displayName: Joi.string().default(undefined),
|
||||
})
|
||||
.optionalKeys(["avatar"]);
|
||||
|
||||
export const SSODisplayNameUserProfileSchema = SSOUserProfileSchema.keys({
|
||||
displayName: Joi.string().default(undefined),
|
||||
}).optionalKeys(["displayName"]);
|
||||
.optionalKeys(["avatar", "displayName"]);
|
||||
|
||||
export async function findOrCreateSSOUser(
|
||||
db: Db,
|
||||
tenant: Tenant,
|
||||
integration: GQLSSOAuthIntegration,
|
||||
token: SSOToken
|
||||
) {
|
||||
if (!token.user) {
|
||||
@@ -49,9 +50,7 @@ export async function findOrCreateSSOUser(
|
||||
|
||||
// Unpack/validate the token content.
|
||||
const { id, email, username, displayName, avatar }: SSOUserProfile = validate(
|
||||
tenant.auth.integrations.sso!.displayNameEnable
|
||||
? SSODisplayNameUserProfileSchema
|
||||
: SSOUserProfileSchema,
|
||||
SSOUserProfileSchema,
|
||||
token.user
|
||||
);
|
||||
|
||||
@@ -63,6 +62,11 @@ export async function findOrCreateSSOUser(
|
||||
// Try to lookup user given their id provided in the `sub` claim.
|
||||
let user = await retrieveUserWithProfile(db, tenant.id, profile);
|
||||
if (!user) {
|
||||
if (!integration.allowRegistration) {
|
||||
// Registration is disabled, so we can't create the user user here.
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: (wyattjoh) implement rules! Not all users should be able to create an account via this method.
|
||||
|
||||
// Create the new user, as one didn't exist before!
|
||||
@@ -138,6 +142,6 @@ export class SSOVerifier {
|
||||
algorithms: ["HS256"], // TODO: (wyattjoh) investigate replacing algorithm.
|
||||
});
|
||||
|
||||
return findOrCreateSSOUser(this.mongo, tenant, token);
|
||||
return findOrCreateSSOUser(this.mongo, tenant, integration, token);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user