@things-factory/auth-base 8.0.5 → 8.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/auth.ts +0 -4
- package/dist-client/auth.js +0 -3
- package/dist-client/auth.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/constants/error-code.d.ts +2 -0
- package/dist-server/constants/error-code.js +3 -1
- package/dist-server/constants/error-code.js.map +1 -1
- package/dist-server/controllers/change-pwd.js +2 -2
- package/dist-server/controllers/change-pwd.js.map +1 -1
- package/dist-server/controllers/delete-user.js +13 -12
- package/dist-server/controllers/delete-user.js.map +1 -1
- package/dist-server/controllers/invitation.d.ts +2 -1
- package/dist-server/controllers/invitation.js +30 -5
- package/dist-server/controllers/invitation.js.map +1 -1
- package/dist-server/controllers/profile.d.ts +4 -3
- package/dist-server/controllers/profile.js +20 -2
- package/dist-server/controllers/profile.js.map +1 -1
- package/dist-server/controllers/signin.d.ts +4 -1
- package/dist-server/controllers/signin.js +17 -1
- package/dist-server/controllers/signin.js.map +1 -1
- package/dist-server/controllers/signup.js +13 -4
- package/dist-server/controllers/signup.js.map +1 -1
- package/dist-server/controllers/unlock-user.js +1 -0
- package/dist-server/controllers/unlock-user.js.map +1 -1
- package/dist-server/controllers/verification.js +1 -0
- package/dist-server/controllers/verification.js.map +1 -1
- package/dist-server/middlewares/domain-authenticate-middleware.js +0 -4
- package/dist-server/middlewares/domain-authenticate-middleware.js.map +1 -1
- package/dist-server/middlewares/signin-middleware.js +5 -4
- package/dist-server/middlewares/signin-middleware.js.map +1 -1
- package/dist-server/middlewares/webauthn-middleware.js +9 -6
- package/dist-server/middlewares/webauthn-middleware.js.map +1 -1
- package/dist-server/migrations/1548206416130-SeedUser.js +2 -1
- package/dist-server/migrations/1548206416130-SeedUser.js.map +1 -1
- package/dist-server/router/auth-checkin-router.js +16 -9
- package/dist-server/router/auth-checkin-router.js.map +1 -1
- package/dist-server/router/auth-private-process-router.js +24 -11
- package/dist-server/router/auth-private-process-router.js.map +1 -1
- package/dist-server/router/auth-public-process-router.js +20 -9
- package/dist-server/router/auth-public-process-router.js.map +1 -1
- package/dist-server/router/auth-signin-router.js +10 -4
- package/dist-server/router/auth-signin-router.js.map +1 -1
- package/dist-server/router/webauthn-router.js.map +1 -1
- package/dist-server/routes.js +5 -4
- package/dist-server/routes.js.map +1 -1
- package/dist-server/service/invitation/invitation-mutation.d.ts +3 -2
- package/dist-server/service/invitation/invitation-mutation.js +20 -8
- package/dist-server/service/invitation/invitation-mutation.js.map +1 -1
- package/dist-server/service/user/user-mutation.d.ts +10 -9
- package/dist-server/service/user/user-mutation.js +112 -54
- package/dist-server/service/user/user-mutation.js.map +1 -1
- package/dist-server/service/user/user-types.d.ts +1 -0
- package/dist-server/service/user/user-types.js +4 -0
- package/dist-server/service/user/user-types.js.map +1 -1
- package/dist-server/service/user/user.d.ts +1 -0
- package/dist-server/service/user/user.js +40 -14
- package/dist-server/service/user/user.js.map +1 -1
- package/dist-server/service/web-auth-credential/web-auth-credential.js.map +1 -1
- package/dist-server/templates/account-unlock-email.d.ts +2 -1
- package/dist-server/templates/account-unlock-email.js +1 -1
- package/dist-server/templates/account-unlock-email.js.map +1 -1
- package/dist-server/templates/invitation-email.d.ts +2 -1
- package/dist-server/templates/invitation-email.js +1 -1
- package/dist-server/templates/invitation-email.js.map +1 -1
- package/dist-server/templates/verification-email.d.ts +2 -1
- package/dist-server/templates/verification-email.js +1 -1
- package/dist-server/templates/verification-email.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/dist-server/utils/access-token-cookie.js +0 -9
- package/dist-server/utils/access-token-cookie.js.map +1 -1
- package/dist-server/utils/check-user-has-role.d.ts +1 -1
- package/dist-server/utils/check-user-has-role.js +2 -2
- package/dist-server/utils/check-user-has-role.js.map +1 -1
- package/dist-server/utils/get-user-domains.d.ts +1 -2
- package/dist-server/utils/get-user-domains.js +27 -23
- package/dist-server/utils/get-user-domains.js.map +1 -1
- package/package.json +9 -9
- package/server/constants/error-code.ts +2 -0
- package/server/controllers/change-pwd.ts +3 -2
- package/server/controllers/delete-user.ts +16 -13
- package/server/controllers/invitation.ts +36 -5
- package/server/controllers/profile.ts +29 -2
- package/server/controllers/signin.ts +21 -2
- package/server/controllers/signup.ts +16 -4
- package/server/controllers/unlock-user.ts +1 -0
- package/server/controllers/verification.ts +1 -0
- package/server/middlewares/domain-authenticate-middleware.ts +0 -5
- package/server/middlewares/signin-middleware.ts +5 -4
- package/server/middlewares/webauthn-middleware.ts +14 -10
- package/server/migrations/1548206416130-SeedUser.ts +2 -1
- package/server/router/auth-checkin-router.ts +19 -11
- package/server/router/auth-private-process-router.ts +26 -11
- package/server/router/auth-public-process-router.ts +22 -10
- package/server/router/auth-signin-router.ts +27 -16
- package/server/router/webauthn-router.ts +6 -8
- package/server/routes.ts +13 -4
- package/server/service/invitation/invitation-mutation.ts +24 -9
- package/server/service/user/user-mutation.ts +123 -54
- package/server/service/user/user-types.ts +3 -0
- package/server/service/user/user.ts +41 -14
- package/server/service/web-auth-credential/web-auth-credential.ts +0 -1
- package/server/templates/account-unlock-email.ts +1 -1
- package/server/templates/invitation-email.ts +1 -1
- package/server/templates/verification-email.ts +1 -1
- package/server/utils/access-token-cookie.ts +0 -11
- package/server/utils/check-user-has-role.ts +2 -2
- package/server/utils/get-user-domains.ts +30 -27
- package/translations/en.json +5 -1
- package/translations/ja.json +5 -1
- package/translations/ko.json +6 -3
- package/translations/ms.json +5 -1
- package/translations/zh.json +5 -1
- package/dist-server/utils/get-domain-from-hostname.d.ts +0 -1
- package/dist-server/utils/get-domain-from-hostname.js +0 -9
- package/dist-server/utils/get-domain-from-hostname.js.map +0 -1
- package/server/utils/get-domain-from-hostname.ts +0 -7
@@ -4,7 +4,6 @@ exports.getAccessTokenCookie = getAccessTokenCookie;
|
|
4
4
|
exports.setAccessTokenCookie = setAccessTokenCookie;
|
5
5
|
exports.setSessionAccessToken = setSessionAccessToken;
|
6
6
|
exports.clearAccessTokenCookie = clearAccessTokenCookie;
|
7
|
-
const shell_1 = require("@things-factory/shell");
|
8
7
|
const env_1 = require("@things-factory/env");
|
9
8
|
const max_age_1 = require("../constants/max-age");
|
10
9
|
const accessTokenCookieKey = env_1.config.get('accessTokenCookieKey', 'access_token');
|
@@ -20,10 +19,6 @@ function setAccessTokenCookie(context, token) {
|
|
20
19
|
maxAge: max_age_1.MAX_AGE,
|
21
20
|
sameSite: 'Lax'
|
22
21
|
};
|
23
|
-
const cookieDomain = (0, shell_1.getCookieDomainFromHostname)(context.hostname);
|
24
|
-
if (cookieDomain) {
|
25
|
-
cookie['domain'] = cookieDomain;
|
26
|
-
}
|
27
22
|
context.cookies.set(accessTokenCookieKey, token, cookie);
|
28
23
|
}
|
29
24
|
function setSessionAccessToken(context) {
|
@@ -42,10 +37,6 @@ function clearAccessTokenCookie(context) {
|
|
42
37
|
httpOnly: true,
|
43
38
|
sameSite: 'Lax'
|
44
39
|
};
|
45
|
-
const cookieDomain = (0, shell_1.getCookieDomainFromHostname)(context.hostname);
|
46
|
-
if (cookieDomain) {
|
47
|
-
cookie['domain'] = cookieDomain;
|
48
|
-
}
|
49
40
|
context.cookies.set(accessTokenCookieKey, '', cookie);
|
50
41
|
/*
|
51
42
|
* TODO clear i18next cookie as well - need to support domain
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"access-token-cookie.js","sourceRoot":"","sources":["../../server/utils/access-token-cookie.ts"],"names":[],"mappings":";;
|
1
|
+
{"version":3,"file":"access-token-cookie.js","sourceRoot":"","sources":["../../server/utils/access-token-cookie.ts"],"names":[],"mappings":";;AAKA,oDAEC;AAED,oDAWC;AAED,sDASC;AAED,wDAgBC;AAjDD,6CAA4C;AAC5C,kDAA8C;AAE9C,MAAM,oBAAoB,GAAG,YAAM,CAAC,GAAG,CAAC,sBAAsB,EAAE,cAAc,CAAC,CAAA;AAE/E,SAAgB,oBAAoB,CAAC,OAAO;;IAC1C,OAAO,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,OAAO,0CAAE,GAAG,CAAC,oBAAoB,CAAC,CAAA;AACpD,CAAC;AAED,SAAgB,oBAAoB,CAAC,OAAO,EAAE,KAAK;IACjD,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAA;IAE1B,IAAI,MAAM,GAAG;QACX,MAAM;QACN,QAAQ,EAAE,IAAI;QACd,MAAM,EAAE,iBAAO;QACf,QAAQ,EAAE,KAAK;KAChB,CAAA;IAED,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,KAAK,EAAE,MAAM,CAAC,CAAA;AAC1D,CAAC;AAED,SAAgB,qBAAqB,CAAC,OAAO;IAC3C,0FAA0F;IAC1F,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;IAE9B,OAAO,CAAC,OAAO,GAAG;QAChB,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,QAAQ,EAAE,IAAI,CAAC,IAAI;QACnB,MAAM,EAAE,IAAI,CAAC,KAAK;KACnB,CAAA;AACH,CAAC;AAED,SAAgB,sBAAsB,CAAC,OAAO;IAC5C,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAA;IAE1B,IAAI,MAAM,GAAG;QACX,MAAM;QACN,QAAQ,EAAE,IAAI;QACd,QAAQ,EAAE,KAAK;KAChB,CAAA;IAED,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,EAAE,EAAE,MAAM,CAAC,CAAA;IACrD;;;OAGG;IACH,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,EAAE,MAAM,CAAC,CAAA;IAC1C,OAAO,CAAC,OAAO,GAAG,IAAI,CAAA;AACxB,CAAC","sourcesContent":["import { config } from '@things-factory/env'\nimport { MAX_AGE } from '../constants/max-age'\n\nconst accessTokenCookieKey = config.get('accessTokenCookieKey', 'access_token')\n\nexport function getAccessTokenCookie(context) {\n return context?.cookies?.get(accessTokenCookieKey)\n}\n\nexport function setAccessTokenCookie(context, token) {\n const { secure } = context\n\n var cookie = {\n secure,\n httpOnly: true,\n maxAge: MAX_AGE,\n sameSite: 'Lax'\n }\n\n context.cookies.set(accessTokenCookieKey, token, cookie)\n}\n\nexport function setSessionAccessToken(context) {\n /* koa-session 을 사용하는 경우에는, cookie 직접 설정이 작동되지 않는다. 그런 경우에는 session에 설정해서 cookie를 변경한다. */\n const { user } = context.state\n\n context.session = {\n id: user.id,\n userType: user.type,\n status: user.state\n }\n}\n\nexport function clearAccessTokenCookie(context) {\n const { secure } = context\n\n var cookie = {\n secure,\n httpOnly: true,\n sameSite: 'Lax'\n }\n\n context.cookies.set(accessTokenCookieKey, '', cookie)\n /*\n * TODO clear i18next cookie as well - need to support domain\n * https://github.com/hatiolab/things-factory/issues/70\n */\n context.cookies.set('i18next', '', cookie)\n context.session = null\n}\n"]}
|
@@ -2,7 +2,7 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.checkUserHasRole = checkUserHasRole;
|
4
4
|
const shell_1 = require("@things-factory/shell");
|
5
|
-
const
|
5
|
+
const user_js_1 = require("../service/user/user.js");
|
6
6
|
/**
|
7
7
|
* @description 사용자가 특정 도메인 또는 상위 도메인에서 특정 역할을 가지고 있는지 확인합니다.
|
8
8
|
*
|
@@ -16,7 +16,7 @@ async function checkUserHasRole(roleId, domain, user) {
|
|
16
16
|
if (!roleId) {
|
17
17
|
return true;
|
18
18
|
}
|
19
|
-
const me = await (0, shell_1.getRepository)(
|
19
|
+
const me = await (0, shell_1.getRepository)(user_js_1.User).findOne({
|
20
20
|
where: { id: user.id },
|
21
21
|
relations: ['roles']
|
22
22
|
});
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"check-user-has-role.js","sourceRoot":"","sources":["../../server/utils/check-user-has-role.ts"],"names":[],"mappings":";;AAcA,4CAcC;AA5BD,iDAA6D;AAE7D
|
1
|
+
{"version":3,"file":"check-user-has-role.js","sourceRoot":"","sources":["../../server/utils/check-user-has-role.ts"],"names":[],"mappings":";;AAcA,4CAcC;AA5BD,iDAA6D;AAE7D,qDAA8C;AAG9C;;;;;;;;GAQG;AACI,KAAK,UAAU,gBAAgB,CAAC,MAAc,EAAE,MAAc,EAAE,IAAU;IAC/E,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,IAAI,CAAA;IACb,CAAC;IAED,MAAM,EAAE,GAAG,MAAM,IAAA,qBAAa,EAAC,cAAI,CAAC,CAAC,OAAO,CAAC;QAC3C,KAAK,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE;QACtB,SAAS,EAAE,CAAC,OAAO,CAAC;KACrB,CAAC,CAAA;IAEF,OAAO,EAAE,CAAC,KAAK;SACZ,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ,CAAC,CAAC;SACrG,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;SACpB,QAAQ,CAAC,MAAM,CAAC,CAAA;AACrB,CAAC","sourcesContent":["import { Domain, getRepository } from '@things-factory/shell'\n\nimport { User } from '../service/user/user.js'\nimport { Role } from '../service/role/role.js'\n\n/**\n * @description 사용자가 특정 도메인 또는 상위 도메인에서 특정 역할을 가지고 있는지 확인합니다.\n *\n * @param roleId 확인할 역할의 ID\n * @param domain 역할을 확인할 도메인\n * @param user 역할을 확인할 사용자\n *\n * @returns 사용자가 도메인 또는 상위 도메인에서 역할을 가지고 있는지 여부를 나타내는 boolean을 반환하는 Promise\n */\nexport async function checkUserHasRole(roleId: string, domain: Domain, user: User): Promise<Boolean> {\n if (!roleId) {\n return true\n }\n\n const me = await getRepository(User).findOne({\n where: { id: user.id },\n relations: ['roles']\n })\n\n return me.roles\n .filter(role => role.domainId === domain.id || (domain.parentId && role.domainId === domain.parentId))\n .map(role => role.id)\n .includes(roleId)\n}\n"]}
|
@@ -1,6 +1,5 @@
|
|
1
1
|
import { Domain } from '@things-factory/shell';
|
2
2
|
import { User } from '../service/user/user';
|
3
|
-
export declare function getUserDomains(user: User): Promise<Partial<Domain>[]>;
|
4
|
-
export declare function getRoleBasedDomains(user: User): Promise<Partial<Domain>[]>;
|
3
|
+
export declare function getUserDomains(user: User, extType?: string): Promise<Partial<Domain>[]>;
|
5
4
|
export declare function getDomainsWithPrivilege(user: User, privilege: string, category: string): Promise<Partial<Domain>[]>;
|
6
5
|
export declare function getDomainsAsOwner(user: User): Promise<Partial<Domain>[]>;
|
@@ -1,12 +1,11 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.getUserDomains = getUserDomains;
|
4
|
-
exports.getRoleBasedDomains = getRoleBasedDomains;
|
5
4
|
exports.getDomainsWithPrivilege = getDomainsWithPrivilege;
|
6
5
|
exports.getDomainsAsOwner = getDomainsAsOwner;
|
7
6
|
const shell_1 = require("@things-factory/shell");
|
8
7
|
const user_1 = require("../service/user/user");
|
9
|
-
async function getUserDomains(user) {
|
8
|
+
async function getUserDomains(user, extType) {
|
10
9
|
return (await (0, shell_1.getRepository)(shell_1.Domain)
|
11
10
|
.createQueryBuilder('DOMAIN')
|
12
11
|
.where(qb => {
|
@@ -31,31 +30,36 @@ async function getUserDomains(user) {
|
|
31
30
|
return 'DOMAIN.id IN ' + subQuery;
|
32
31
|
})
|
33
32
|
.orderBy('DOMAIN.name', 'ASC')
|
34
|
-
.getMany())
|
35
|
-
|
36
|
-
|
37
|
-
});
|
38
|
-
}
|
39
|
-
async function getRoleBasedDomains(user) {
|
40
|
-
return (await (0, shell_1.getRepository)(shell_1.Domain)
|
41
|
-
.createQueryBuilder('DOMAIN')
|
42
|
-
.where(qb => {
|
43
|
-
const subQuery = qb
|
44
|
-
.subQuery()
|
45
|
-
.distinct(true)
|
46
|
-
.select('DOMAIN.id')
|
47
|
-
.from(user_1.User, 'USER')
|
48
|
-
.leftJoin('USER.roles', 'ROLE')
|
49
|
-
.leftJoin('ROLE.domain', 'DOMAIN')
|
50
|
-
.where('USER.id = :userId', { userId: user.id })
|
51
|
-
.getQuery();
|
52
|
-
return 'DOMAIN.id IN ' + subQuery;
|
53
|
-
})
|
54
|
-
.getMany()).map(domain => {
|
33
|
+
.getMany())
|
34
|
+
.filter(domain => !extType || domain.extType == extType)
|
35
|
+
.map(domain => {
|
55
36
|
const { id, name, description, subdomain, extType, brandName, brandImage } = domain;
|
37
|
+
/* do not remove id column for result */
|
56
38
|
return { id, name, description, subdomain, extType, brandName, brandImage };
|
57
39
|
});
|
58
40
|
}
|
41
|
+
// export async function getRoleBasedDomains(user: User): Promise<Partial<Domain>[]> {
|
42
|
+
// return (
|
43
|
+
// await getRepository(Domain)
|
44
|
+
// .createQueryBuilder('DOMAIN')
|
45
|
+
// .where(qb => {
|
46
|
+
// const subQuery = qb
|
47
|
+
// .subQuery()
|
48
|
+
// .distinct(true)
|
49
|
+
// .select('DOMAIN.id')
|
50
|
+
// .from(User, 'USER')
|
51
|
+
// .leftJoin('USER.roles', 'ROLE')
|
52
|
+
// .leftJoin('ROLE.domain', 'DOMAIN')
|
53
|
+
// .where('USER.id = :userId', { userId: user.id })
|
54
|
+
// .getQuery()
|
55
|
+
// return 'DOMAIN.id IN ' + subQuery
|
56
|
+
// })
|
57
|
+
// .getMany()
|
58
|
+
// ).map(domain => {
|
59
|
+
// const { id, name, description, subdomain, extType, brandName, brandImage } = domain
|
60
|
+
// return { id, name, description, subdomain, extType, brandName, brandImage }
|
61
|
+
// })
|
62
|
+
// }
|
59
63
|
async function getDomainsWithPrivilege(user, privilege, category) {
|
60
64
|
return (await (0, shell_1.getRepository)(shell_1.Domain)
|
61
65
|
.createQueryBuilder('DOMAIN')
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"get-user-domains.js","sourceRoot":"","sources":["../../server/utils/get-user-domains.ts"],"names":[],"mappings":";;AAMA,
|
1
|
+
{"version":3,"file":"get-user-domains.js","sourceRoot":"","sources":["../../server/utils/get-user-domains.ts"],"names":[],"mappings":"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","sourcesContent":["import { In } from 'typeorm'\n\nimport { Domain, getRepository } from '@things-factory/shell'\n\nimport { User } from '../service/user/user'\n\nexport async function getUserDomains(user: User, extType?: string): Promise<Partial<Domain>[]> {\n return (\n await getRepository(Domain)\n .createQueryBuilder('DOMAIN')\n .where(qb => {\n const subQuery = qb\n .subQuery()\n .distinct(true)\n .select('DOMAIN.id')\n .from(User, 'USER')\n .leftJoin('USER.roles', 'ROLE')\n .leftJoin('ROLE.domain', 'DOMAIN')\n .where('USER.id = :userId', { userId: user.id })\n .getQuery()\n return 'DOMAIN.id IN ' + subQuery\n })\n .orWhere(qb => {\n const subQuery = qb\n .subQuery()\n .select('DOMAIN.id')\n .from(Domain, 'DOMAIN')\n .where('DOMAIN.owner = :owner', { owner: user.id })\n .getQuery()\n return 'DOMAIN.id IN ' + subQuery\n })\n .orderBy('DOMAIN.name', 'ASC')\n .getMany()\n )\n .filter(domain => !extType || domain.extType == extType)\n .map(domain => {\n const { id, name, description, subdomain, extType, brandName, brandImage } = domain\n /* do not remove id column for result */\n return { id, name, description, subdomain, extType, brandName, brandImage }\n })\n}\n\n// export async function getRoleBasedDomains(user: User): Promise<Partial<Domain>[]> {\n// return (\n// await getRepository(Domain)\n// .createQueryBuilder('DOMAIN')\n// .where(qb => {\n// const subQuery = qb\n// .subQuery()\n// .distinct(true)\n// .select('DOMAIN.id')\n// .from(User, 'USER')\n// .leftJoin('USER.roles', 'ROLE')\n// .leftJoin('ROLE.domain', 'DOMAIN')\n// .where('USER.id = :userId', { userId: user.id })\n// .getQuery()\n// return 'DOMAIN.id IN ' + subQuery\n// })\n// .getMany()\n// ).map(domain => {\n// const { id, name, description, subdomain, extType, brandName, brandImage } = domain\n// return { id, name, description, subdomain, extType, brandName, brandImage }\n// })\n// }\n\nexport async function getDomainsWithPrivilege(\n user: User,\n privilege: string,\n category: string\n): Promise<Partial<Domain>[]> {\n return (\n await getRepository(Domain)\n .createQueryBuilder('DOMAIN')\n .where(qb => {\n const subQuery = qb\n .subQuery()\n .distinct(true)\n .select('DOMAIN.id')\n .from(User, 'USER')\n .leftJoin('USER.roles', 'ROLE')\n .leftJoin('ROLE.domain', 'DOMAIN')\n .leftJoin('ROLE.privileges', 'PRIVILEGE')\n .where('USER.id = :userId', { userId: user.id })\n .andWhere('PRIVILEGE.name = :privilege', { privilege })\n .andWhere('PRIVILEGE.category = :category', { category })\n .getQuery()\n return 'DOMAIN.id IN ' + subQuery\n })\n .orWhere(qb => {\n const subQuery = qb\n .subQuery()\n .select('DOMAIN.id')\n .from(Domain, 'DOMAIN')\n .where('DOMAIN.owner = :owner', { owner: user.id })\n .getQuery()\n return 'DOMAIN.id IN ' + subQuery\n })\n .orderBy('DOMAIN.name', 'ASC')\n .getMany()\n ).map(domain => {\n const { id, name, description, subdomain, extType, brandName, brandImage } = domain\n return { id, name, description, subdomain, extType, brandName, brandImage }\n })\n}\n\nexport async function getDomainsAsOwner(user: User): Promise<Partial<Domain>[]> {\n return (\n await getRepository(Domain).find({\n where: { owner: user.id }\n })\n ).map(domain => {\n const { id, name, description, subdomain, extType, brandName, brandImage } = domain\n return { id, name, description, subdomain, extType, brandName, brandImage }\n })\n}\n"]}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@things-factory/auth-base",
|
3
|
-
"version": "8.0.
|
3
|
+
"version": "8.0.13",
|
4
4
|
"main": "dist-server/index.js",
|
5
5
|
"browser": "dist-client/index.js",
|
6
6
|
"things-factory": true,
|
@@ -30,13 +30,13 @@
|
|
30
30
|
"migration:create": "node ../../node_modules/typeorm/cli.js migration:create ./server/migrations/migration"
|
31
31
|
},
|
32
32
|
"dependencies": {
|
33
|
-
"@simplewebauthn/browser": "^
|
34
|
-
"@simplewebauthn/server": "^
|
35
|
-
"@things-factory/email-base": "^8.0.
|
36
|
-
"@things-factory/env": "^8.0.
|
37
|
-
"@things-factory/shell": "^8.0.
|
38
|
-
"@things-factory/utils": "^8.0.
|
39
|
-
"@types/webappsec-credential-management": "^0.6.
|
33
|
+
"@simplewebauthn/browser": "^13.0.0",
|
34
|
+
"@simplewebauthn/server": "^13.0.0",
|
35
|
+
"@things-factory/email-base": "^8.0.13",
|
36
|
+
"@things-factory/env": "^8.0.8",
|
37
|
+
"@things-factory/shell": "^8.0.13",
|
38
|
+
"@things-factory/utils": "^8.0.8",
|
39
|
+
"@types/webappsec-credential-management": "^0.6.9",
|
40
40
|
"jsonwebtoken": "^9.0.0",
|
41
41
|
"koa-passport": "^6.0.0",
|
42
42
|
"koa-session": "^6.4.0",
|
@@ -46,5 +46,5 @@
|
|
46
46
|
"passport-jwt": "^4.0.0",
|
47
47
|
"passport-local": "^1.0.0"
|
48
48
|
},
|
49
|
-
"gitHead": "
|
49
|
+
"gitHead": "66c1356c18b5c9a21e8280460eb40020f7ea2b37"
|
50
50
|
}
|
@@ -17,4 +17,6 @@ export const PASSWORD_USED_PAST = 'password used in the past'
|
|
17
17
|
export const VERIFICATION_ERROR = 'user or verification token not found'
|
18
18
|
export const AUTHN_VERIFICATION_FAILED = 'authn verification failed'
|
19
19
|
export const USER_CREDENTIAL_NOT_FOUND = 'user credential not found'
|
20
|
+
export const EMAIL_ALREADY_EXISTS = 'email already exists'
|
21
|
+
export const USERNAME_ALREADY_EXISTS = 'email already exists'
|
20
22
|
export const AUTH_ERROR = 'auth error'
|
@@ -1,4 +1,3 @@
|
|
1
|
-
import { ILike } from 'typeorm'
|
2
1
|
import { config } from '@things-factory/env'
|
3
2
|
import { getRepository } from '@things-factory/shell'
|
4
3
|
|
@@ -19,7 +18,8 @@ export async function changePwd(attrs, currentPass, newPass, confirmPass, contex
|
|
19
18
|
|
20
19
|
// TODO 이 사용자가 이 도메인에 속한 사용자인지 확인해야함.
|
21
20
|
const repository = getRepository(User)
|
22
|
-
|
21
|
+
|
22
|
+
const user: User = await repository.findOne({ where: { id: attrs.id } })
|
23
23
|
|
24
24
|
if (!user) {
|
25
25
|
throw new AuthError({
|
@@ -37,6 +37,7 @@ export async function changePwd(attrs, currentPass, newPass, confirmPass, contex
|
|
37
37
|
throw new AuthError({
|
38
38
|
errorCode: PASSWORD_NOT_MATCHED,
|
39
39
|
detail: {
|
40
|
+
username: user.username,
|
40
41
|
email: user.email,
|
41
42
|
failCount: user.failCount
|
42
43
|
}
|
@@ -8,7 +8,20 @@ export async function deleteUser(attrs, tx?: EntityManager) {
|
|
8
8
|
// TODO 다른 도메인에도 포함되어있다면, domains-users 관게와 해당 도메인 관련 정보만 삭제해야 함.
|
9
9
|
|
10
10
|
const repository = tx?.getRepository(User)
|
11
|
-
const
|
11
|
+
const { username } = attrs
|
12
|
+
|
13
|
+
var user = await repository.findOne({
|
14
|
+
where: { username },
|
15
|
+
relations: ['domains']
|
16
|
+
})
|
17
|
+
|
18
|
+
if (!user && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(username)) {
|
19
|
+
user = await repository.findOne({
|
20
|
+
where: { email: ILike(username) },
|
21
|
+
relations: ['domains']
|
22
|
+
})
|
23
|
+
}
|
24
|
+
|
12
25
|
if (!user) {
|
13
26
|
throw new AuthError({
|
14
27
|
errorCode: USER_NOT_FOUND
|
@@ -19,29 +32,19 @@ export async function deleteUser(attrs, tx?: EntityManager) {
|
|
19
32
|
user.domains = []
|
20
33
|
|
21
34
|
await repository.save(user)
|
22
|
-
|
23
|
-
// repository api는 작동하지 않음.
|
24
|
-
// await txManager
|
25
|
-
// .createQueryBuilder()
|
26
|
-
// .delete()
|
27
|
-
// .from('users_domains')
|
28
|
-
// .where({
|
29
|
-
// usersId: user.id
|
30
|
-
// })
|
31
|
-
// .execute()
|
32
35
|
}
|
33
36
|
|
34
37
|
export async function deleteUsers(attrs, tx?: EntityManager) {
|
35
38
|
// TODO 이 사용자가 이 도메인에 속한 사용자인지 확인해야함.
|
36
39
|
// TODO 다른 도메인에도 포함되어있다면, domains-users 관게와 해당 도메인 관련 정보만 삭제해야 함.
|
37
40
|
|
38
|
-
const {
|
41
|
+
const { usernames } = attrs
|
39
42
|
|
40
43
|
const repo = tx?.getRepository(User)
|
41
44
|
|
42
45
|
const users = await repo.find({
|
43
46
|
where: {
|
44
|
-
|
47
|
+
username: In(usernames)
|
45
48
|
}
|
46
49
|
})
|
47
50
|
|
@@ -5,15 +5,27 @@ import { sendEmail } from '@things-factory/email-base'
|
|
5
5
|
import { Domain, getRepository } from '@things-factory/shell'
|
6
6
|
|
7
7
|
import { Invitation } from '../service/invitation/invitation'
|
8
|
-
import { User } from '../service/user/user'
|
8
|
+
import { User, UserStatus } from '../service/user/user'
|
9
9
|
import { getInvitationEmailForm } from '../templates/invitation-email'
|
10
10
|
import { makeInvitationToken } from './utils/make-invitation-token'
|
11
11
|
import { saveInvitationToken } from './utils/save-invitation-token'
|
12
12
|
|
13
13
|
export async function invite(attrs, withEmailInvitation?: Boolean) {
|
14
|
-
const {
|
14
|
+
const { username, reference, type, context } = attrs
|
15
|
+
const repository = getRepository(User)
|
16
|
+
|
17
|
+
var user = await repository.findOne({
|
18
|
+
where: { username },
|
19
|
+
relations: ['domains']
|
20
|
+
})
|
21
|
+
|
22
|
+
if (!user && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(username)) {
|
23
|
+
user = await repository.findOne({
|
24
|
+
where: { email: ILike(username) },
|
25
|
+
relations: ['domains']
|
26
|
+
})
|
27
|
+
}
|
15
28
|
|
16
|
-
var user = await getRepository(User).findOne({ where: { email: ILike(email) }, relations: ['domains'] })
|
17
29
|
var domains = user.domains
|
18
30
|
|
19
31
|
// TODO reference should not be a domain.id (security reason)
|
@@ -28,6 +40,9 @@ export async function invite(attrs, withEmailInvitation?: Boolean) {
|
|
28
40
|
}
|
29
41
|
|
30
42
|
if (withEmailInvitation) {
|
43
|
+
const email = user.email
|
44
|
+
|
45
|
+
// TODO 초대장의 유효기간을 설정할 수 있어야 함.
|
31
46
|
var invitation = await getRepository(Invitation).findOneBy({
|
32
47
|
email: ILike(email),
|
33
48
|
reference,
|
@@ -44,6 +59,7 @@ export async function invite(attrs, withEmailInvitation?: Boolean) {
|
|
44
59
|
|
45
60
|
return await sendInvitationEmail({
|
46
61
|
invitation,
|
62
|
+
user,
|
47
63
|
context
|
48
64
|
})
|
49
65
|
}
|
@@ -89,7 +105,7 @@ export async function acceptInvitation(token) {
|
|
89
105
|
return true
|
90
106
|
}
|
91
107
|
|
92
|
-
export async function sendInvitationEmail({ invitation, context }) {
|
108
|
+
export async function sendInvitationEmail({ invitation, user, context }) {
|
93
109
|
try {
|
94
110
|
var token = makeInvitationToken()
|
95
111
|
var verifaction = await saveInvitationToken(invitation.id, token)
|
@@ -101,6 +117,7 @@ export async function sendInvitationEmail({ invitation, context }) {
|
|
101
117
|
receiver: invitation.email,
|
102
118
|
subject: 'Invitation',
|
103
119
|
content: getInvitationEmailForm({
|
120
|
+
username: user.username,
|
104
121
|
email: invitation.email,
|
105
122
|
acceptUrl: serviceUrl
|
106
123
|
})
|
@@ -123,10 +140,24 @@ export async function resendInvitationEmail(
|
|
123
140
|
type
|
124
141
|
})
|
125
142
|
|
126
|
-
if (!invitation)
|
143
|
+
if (!invitation) {
|
144
|
+
throw new Error(`not found invitation.`)
|
145
|
+
}
|
146
|
+
|
147
|
+
var user = await getRepository(User).findOne({
|
148
|
+
where: {
|
149
|
+
email: ILike(email),
|
150
|
+
status: UserStatus.ACTIVATED
|
151
|
+
}
|
152
|
+
})
|
153
|
+
|
154
|
+
if (!user) {
|
155
|
+
throw new Error(`user not found: ${email}`)
|
156
|
+
}
|
127
157
|
|
128
158
|
return await sendInvitationEmail({
|
129
159
|
invitation,
|
160
|
+
user,
|
130
161
|
context
|
131
162
|
})
|
132
163
|
}
|
@@ -1,3 +1,5 @@
|
|
1
|
+
import { ILike } from 'typeorm'
|
2
|
+
|
1
3
|
import { getRepository } from '@things-factory/shell'
|
2
4
|
|
3
5
|
import { USER_NOT_FOUND } from '../constants/error-code'
|
@@ -13,14 +15,39 @@ export async function updateProfile({ id }, newProfiles) {
|
|
13
15
|
})
|
14
16
|
}
|
15
17
|
|
16
|
-
/* only 'name', 'email' and 'locale' attributes can be changed */
|
17
|
-
var allowed
|
18
|
+
/* only 'username', 'name', 'email' and 'locale' attributes can be changed */
|
19
|
+
var allowed: {
|
20
|
+
username?: string
|
21
|
+
name?: string
|
22
|
+
email?: string
|
23
|
+
locale?: string
|
24
|
+
} = ['username', 'name', 'email', 'locale']
|
18
25
|
.filter(attr => attr in newProfiles)
|
19
26
|
.reduce((sum, attr) => {
|
20
27
|
sum[attr] = newProfiles[attr]
|
21
28
|
return sum
|
22
29
|
}, {})
|
23
30
|
|
31
|
+
/* check if email and username is unique */
|
32
|
+
if ('email' in allowed) {
|
33
|
+
var found: User = await repository.findOne({ where: { email: ILike(allowed.email) } })
|
34
|
+
|
35
|
+
if (found && found.id != id) {
|
36
|
+
throw new AuthError({
|
37
|
+
errorCode: AuthError.ERROR_CODES.EMAIL_ALREADY_EXISTS
|
38
|
+
})
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
if ('username' in allowed) {
|
43
|
+
var found: User = await repository.findOne({ where: { username: allowed.username } })
|
44
|
+
if (found && found.id != id) {
|
45
|
+
throw new AuthError({
|
46
|
+
errorCode: AuthError.ERROR_CODES.USERNAME_ALREADY_EXISTS
|
47
|
+
})
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
24
51
|
return await repository.save({
|
25
52
|
...user,
|
26
53
|
...allowed
|
@@ -5,11 +5,26 @@ import { sendUnlockUserEmail } from '../controllers/unlock-user'
|
|
5
5
|
import { AuthError } from '../errors/auth-error'
|
6
6
|
import { User, UserStatus } from '../service/user/user'
|
7
7
|
|
8
|
-
export async function signin(attrs, context?) {
|
8
|
+
export async function signin(attrs: { username: string; password: string }, context?) {
|
9
9
|
const { domain } = context?.state || {}
|
10
|
+
const { username } = attrs
|
10
11
|
|
11
12
|
const repository = getRepository(User)
|
12
|
-
|
13
|
+
|
14
|
+
var user = await repository.findOne({
|
15
|
+
where: { username },
|
16
|
+
relations: ['domains']
|
17
|
+
})
|
18
|
+
|
19
|
+
if (!user && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(username)) {
|
20
|
+
user = await repository.findOne({
|
21
|
+
where: {
|
22
|
+
email: ILike(username)
|
23
|
+
},
|
24
|
+
relations: ['domains']
|
25
|
+
})
|
26
|
+
}
|
27
|
+
|
13
28
|
if (!user)
|
14
29
|
throw new AuthError({
|
15
30
|
errorCode: AuthError.ERROR_CODES.USER_NOT_FOUND
|
@@ -29,6 +44,7 @@ export async function signin(attrs, context?) {
|
|
29
44
|
throw new AuthError({
|
30
45
|
errorCode: AuthError.ERROR_CODES.USER_LOCKED,
|
31
46
|
detail: {
|
47
|
+
username: user.username,
|
32
48
|
email: user.email
|
33
49
|
}
|
34
50
|
})
|
@@ -46,6 +62,7 @@ export async function signin(attrs, context?) {
|
|
46
62
|
throw new AuthError({
|
47
63
|
errorCode: AuthError.ERROR_CODES.USER_LOCKED,
|
48
64
|
detail: {
|
65
|
+
username: user.username,
|
49
66
|
email: user.email
|
50
67
|
}
|
51
68
|
})
|
@@ -53,6 +70,7 @@ export async function signin(attrs, context?) {
|
|
53
70
|
throw new AuthError({
|
54
71
|
errorCode: AuthError.ERROR_CODES.PASSWORD_NOT_MATCHED,
|
55
72
|
detail: {
|
73
|
+
username: user.username,
|
56
74
|
email: user.email,
|
57
75
|
failCount: user.failCount
|
58
76
|
}
|
@@ -66,6 +84,7 @@ export async function signin(attrs, context?) {
|
|
66
84
|
throw new AuthError({
|
67
85
|
errorCode: AuthError.ERROR_CODES.USER_NOT_ACTIVATED,
|
68
86
|
detail: {
|
87
|
+
username: user.username,
|
69
88
|
email: user.email
|
70
89
|
}
|
71
90
|
})
|
@@ -8,19 +8,31 @@ import { signin } from './signin'
|
|
8
8
|
import { sendVerificationEmail } from './verification'
|
9
9
|
|
10
10
|
export async function signup(attrs, withEmailVerification?: Boolean) {
|
11
|
-
const { name,
|
11
|
+
const { name, username, password, domain, context } = attrs
|
12
12
|
|
13
13
|
/* check if password is following the rule */
|
14
14
|
User.validatePasswordByRule(password, context.lng)
|
15
15
|
|
16
16
|
const repository = getRepository(User)
|
17
|
-
|
17
|
+
|
18
|
+
var duplicated = await repository.findOne({
|
19
|
+
where: { username },
|
20
|
+
relations: ['domains']
|
21
|
+
})
|
22
|
+
|
23
|
+
if (!duplicated && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(username)) {
|
24
|
+
user = await repository.findOne({
|
25
|
+
where: { email: ILike(username) },
|
26
|
+
relations: ['domains']
|
27
|
+
})
|
28
|
+
}
|
29
|
+
|
18
30
|
if (duplicated) {
|
19
31
|
throw new AuthError({
|
20
32
|
errorCode: USER_DUPLICATED,
|
21
33
|
detail: {
|
22
34
|
name,
|
23
|
-
|
35
|
+
username
|
24
36
|
}
|
25
37
|
})
|
26
38
|
}
|
@@ -48,7 +60,7 @@ export async function signup(attrs, withEmailVerification?: Boolean) {
|
|
48
60
|
return {
|
49
61
|
token: await signin(
|
50
62
|
{
|
51
|
-
|
63
|
+
username,
|
52
64
|
password
|
53
65
|
},
|
54
66
|
{ domain }
|
@@ -1,14 +1,9 @@
|
|
1
|
-
import { config } from '@things-factory/env'
|
2
1
|
import { Domain, getRepository } from '@things-factory/shell'
|
3
2
|
|
4
3
|
import { AuthError } from '../errors/auth-error'
|
5
4
|
import { User } from '../service/user/user'
|
6
5
|
import { getUserDomains } from '../utils/get-user-domains'
|
7
6
|
|
8
|
-
const useVirtualHostBasedDomain = !!config.get('useVirtualHostBasedDomain')
|
9
|
-
const fixed = config.get('subdomain')
|
10
|
-
const subdomainOffset = config.getNumber('subdomainOffset', 2)
|
11
|
-
|
12
7
|
declare global {
|
13
8
|
namespace NodeJS {
|
14
9
|
interface Process {
|
@@ -7,17 +7,18 @@ passport.use(
|
|
7
7
|
'signin',
|
8
8
|
new localStrategy(
|
9
9
|
{
|
10
|
-
usernameField: '
|
11
|
-
passwordField: 'password'
|
10
|
+
usernameField: 'username',
|
11
|
+
passwordField: 'password',
|
12
|
+
passReqToCallback: true
|
12
13
|
},
|
13
|
-
async (
|
14
|
+
async (req, username, password, done) => {
|
14
15
|
try {
|
15
16
|
const {
|
16
17
|
user: userInfo,
|
17
18
|
token,
|
18
19
|
domains
|
19
20
|
} = await signin({
|
20
|
-
|
21
|
+
username,
|
21
22
|
password
|
22
23
|
})
|
23
24
|
|