[next] Auth Popup v2 (#2101)

* feat: Implement new Sign In view

* feat: Move forgot + resetPassword to new design

* feat: Implement sign up with new design

* fix: narrow gutter

* test: add unit tests

* test: integration tests

* feat: support show / hide password

* feat: support oauth2 flow

* feat: add views for user completion

* feat: implement oauth2 sign up

* test: fix snapshots

* fix: lint

* fix: get more complete mutation response

* fix: removed array of OIDC integrations

* fix: renamed resolver function

* fix: adapt oidc client implementation

* fix: targetFilter should be stream on signup

* fix: removed unneeded message

* fix: moved password into local profile

* fix: made username optional, removed valid null value

* fix: linting

* fix: respect targetFilter

* feat: support user registration mutations

- Added `setUsername`
- Added `setEmail`
- Added `setPassword`
- Added `permit` to `@auth`
- Added `email` to `User`

* fix: fixed issue with query

* feat: added user password update

* feat: complete sign in mutation

* fix: adapt some rebasing gitches

* test: improve tests

* test: unittest for setting auth token

* fix: failing tests

* test: move most tests from enzyme to react-test-renderer

* fix: remove schema warnings in tests

* test: improve window mock

* test: test different social login configurations

* test: test social logins for sign up

* fix: use htmlFor instead of for

* test: more feature tests

* feat: always go through account completion

* test: feature test account completion

* feat: addtional account completion test

* Update start.ts

* chore: refactor auth token retrieval logic
This commit is contained in:
Kiwi
2018-12-20 22:32:04 +01:00
committed by GitHub
parent 326a10dc5d
commit 065cb4b03a
331 changed files with 12476 additions and 7163 deletions
+1 -87
View File
@@ -2,20 +2,13 @@ import { Redis } from "ioredis";
import { Db } from "mongodb";
import { URL } from "url";
import {
GQLCreateOIDCAuthIntegrationConfigurationInput,
GQLSettingsInput,
GQLUpdateOIDCAuthIntegrationConfigurationInput,
} from "talk-server/graph/tenant/schema/__generated__/types";
import { GQLSettingsInput } from "talk-server/graph/tenant/schema/__generated__/types";
import {
createTenant,
CreateTenantInput,
createTenantOIDCAuthIntegration,
regenerateTenantSSOKey,
removeTenantOIDCAuthIntegration,
Tenant,
updateTenant,
updateTenantOIDCAuthIntegration,
} from "talk-server/models/tenant";
import { discover } from "talk-server/app/middleware/passport/strategies/oidc/discover";
@@ -123,82 +116,3 @@ export async function discoverOIDCConfiguration(issuerString: string) {
// Discover the configuration.
return discover(issuer);
}
export type CreateOIDCAuthIntegration = GQLCreateOIDCAuthIntegrationConfigurationInput;
export async function createOIDCAuthIntegration(
mongo: Db,
redis: Redis,
cache: TenantCache,
tenant: Tenant,
input: CreateOIDCAuthIntegration
) {
// Create the integration. By default, the integration is disabled.
const result = await createTenantOIDCAuthIntegration(mongo, tenant.id, {
enabled: false,
allowRegistration: false,
targetFilter: {
admin: true,
stream: true,
},
...input,
});
if (!result.wasCreated || !result.tenant) {
return null;
}
// Update the tenant cache.
await cache.update(redis, result.tenant);
return result;
}
export type UpdateOIDCAuthIntegration = GQLUpdateOIDCAuthIntegrationConfigurationInput;
export async function updateOIDCAuthIntegration(
mongo: Db,
redis: Redis,
cache: TenantCache,
tenant: Tenant,
oidcID: string,
input: UpdateOIDCAuthIntegration
) {
// Update the integration. By default, the integration is disabled.
const result = await updateTenantOIDCAuthIntegration(
mongo,
tenant.id,
oidcID,
input
);
if (!result.wasUpdated || !result.tenant) {
return null;
}
// Update the tenant cache.
await cache.update(redis, result.tenant);
return result;
}
export async function removeOIDCAuthIntegration(
mongo: Db,
redis: Redis,
cache: TenantCache,
tenant: Tenant,
oidcID: string
) {
// Delete the integration. By default, the integration is disabled.
const result = await removeTenantOIDCAuthIntegration(
mongo,
tenant.id,
oidcID
);
if (!result.wasRemoved || !result.tenant) {
return null;
}
// Update the tenant cache.
await cache.update(redis, result.tenant);
return result;
}
+80 -1
View File
@@ -1,7 +1,15 @@
import { Db } from "mongodb";
import { Tenant } from "talk-server/models/tenant";
import { upsertUser, UpsertUserInput } from "talk-server/models/user";
import {
setUserEmail,
setUserLocalProfile,
setUserUsername,
updateUserPassword,
upsertUser,
UpsertUserInput,
User,
} from "talk-server/models/user";
export type UpsertUser = UpsertUserInput;
@@ -10,3 +18,74 @@ export async function upsert(db: Db, tenant: Tenant, input: UpsertUser) {
return user;
}
export async function setUsername(
mongo: Db,
tenant: Tenant,
user: User,
username: string
) {
// We require that the username is not defined in order to use this method.
if (user.username) {
throw new Error("username already associated with user");
}
return setUserUsername(mongo, tenant.id, user.id, username);
}
export async function setEmail(
mongo: Db,
tenant: Tenant,
user: User,
email: string
) {
// We requires that the email address is not defined in order to use this
// method.
if (user.email) {
throw new Error("email address already associated with user");
}
return setUserEmail(mongo, tenant.id, user.id, email);
}
export async function setPassword(
mongo: Db,
tenant: Tenant,
user: User,
password: string
) {
// We require that the email address for the user be defined for this method.
if (!user.email) {
throw new Error("no email address associated with user");
}
// We also don't allow this method to be used by users that already have a
// local profile.
if (user.profiles.some(({ type }) => type === "local")) {
throw new Error("user already has local profile");
}
return setUserLocalProfile(mongo, tenant.id, user.id, user.email, password);
}
export async function updatePassword(
mongo: Db,
tenant: Tenant,
user: User,
password: string
) {
// We require that the email address for the user be defined for this method.
if (!user.email) {
throw new Error("no email address associated with user");
}
// We also don't allow this method to be used by users that don't have a local
// profile already.
if (
!user.profiles.some(({ id, type }) => type === "local" && id === user.email)
) {
throw new Error("user does not have a local profile");
}
return updateUserPassword(mongo, tenant.id, user.id, password);
}