5htp 0.3.5 → 0.3.8
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/package.json +4 -3
- package/skeleton/docker-compose.yml +7 -15
- package/skeleton/identity.yaml +12 -8
- package/skeleton/package.json +25 -7
- package/skeleton/src/client/assets/identity/logo.svg +13 -63
- package/skeleton/src/client/assets/identity/logoAndText.svg +9 -104
- package/skeleton/src/client/assets/identity/logoAndTextBlack.svg +11 -0
- package/skeleton/src/client/assets/illustration/landing/banner.webp +0 -0
- package/skeleton/src/client/assets/illustration/landing/candidate/employers.webp +0 -0
- package/skeleton/src/client/assets/illustration/landing/candidate/hero.webp +0 -0
- package/skeleton/src/client/assets/illustration/landing/candidate/mentors.webp +0 -0
- package/skeleton/src/client/assets/illustration/landing/headhunter/hero.webp +0 -0
- package/skeleton/src/client/assets/illustration/landing/hero.jpeg +0 -0
- package/skeleton/src/client/assets/illustration/landing/hero.webp +0 -0
- package/skeleton/src/client/assets/illustration/landing/hero.xcf +0 -0
- package/skeleton/src/client/assets/illustration/landing/recruiter/onboarding.webp +0 -0
- package/skeleton/src/client/assets/illustration/landing/team/andre.png +0 -0
- package/skeleton/src/client/assets/illustration/landing/team/emma.png +0 -0
- package/skeleton/src/client/assets/illustration/landing/team/fei.png +0 -0
- package/skeleton/src/client/assets/illustration/landing/team/gaetan.png +0 -0
- package/skeleton/src/client/assets/illustration/landing/team/jordan.png +0 -0
- package/skeleton/src/client/assets/illustration/landing/team/lery.png +0 -0
- package/skeleton/src/client/assets/illustration/landing/team/mehdi.png +0 -0
- package/skeleton/src/client/assets/illustration/landing/team/omkar.png +0 -0
- package/skeleton/src/client/assets/illustration/landing/team/thibaut.png +0 -0
- package/skeleton/src/client/assets/img/background/header-blur.png +0 -0
- package/skeleton/src/client/assets/img/partners/citron.svg +987 -0
- package/skeleton/src/client/assets/patterns/dots.png +0 -0
- package/skeleton/src/client/assets/theme.less +179 -226
- package/skeleton/src/client/assets/vars.less +54 -0
- package/skeleton/src/client/context.ts +23 -0
- package/skeleton/src/client/index.ts +59 -0
- package/skeleton/src/client/pages/_messages/400.tsx +45 -0
- package/skeleton/src/client/pages/_messages/401.tsx +39 -0
- package/skeleton/src/client/pages/_messages/403.tsx +43 -0
- package/skeleton/src/client/pages/_messages/404.tsx +42 -0
- package/skeleton/src/client/pages/_messages/500.tsx +42 -0
- package/skeleton/src/client/pages/platform/Header.less +12 -0
- package/skeleton/src/client/pages/platform/Header.tsx +119 -0
- package/skeleton/src/client/pages/platform/_layout/index.less +118 -0
- package/skeleton/src/client/pages/platform/_layout/index.tsx +131 -0
- package/skeleton/src/client/pages/platform/_layout/mobile.less +114 -0
- package/skeleton/src/client/pages/platform/_page.tsx +54 -0
- package/skeleton/src/client/pages/platform/headhunters/index.tsx +88 -0
- package/skeleton/src/client/pages/platform/index.tsx +58 -0
- package/skeleton/src/client/pages/platform/missions/index.tsx +149 -0
- package/skeleton/src/client/services/metrics/index.ts +59 -0
- package/skeleton/src/client/tsconfig.json +4 -1
- package/skeleton/src/common/config/router.ts +16 -0
- package/skeleton/src/common/forms/company/bookCall.ts +25 -0
- package/skeleton/src/common/forms/company/importJob.ts +26 -0
- package/skeleton/src/common/forms/company/signup.ts +31 -0
- package/skeleton/src/common/forms/headhunter/feedback.ts +31 -0
- package/skeleton/src/common/forms/headhunter/mission/cancel.ts +26 -0
- package/skeleton/src/common/forms/headhunter/mission/candidate/availability.ts +31 -0
- package/skeleton/src/common/forms/headhunter/mission/candidate/education.ts +19 -0
- package/skeleton/src/common/forms/headhunter/mission/candidate/identity.ts +31 -0
- package/skeleton/src/common/forms/headhunter/mission/candidate/others.ts +19 -0
- package/skeleton/src/common/forms/headhunter/mission/candidate/skills.ts +21 -0
- package/skeleton/src/common/forms/headhunter/mission/reject.ts +23 -0
- package/skeleton/src/common/forms/headhunter/mission/search.ts +78 -0
- package/skeleton/src/common/forms/headhunter/signup.ts +34 -0
- package/skeleton/src/common/libs/headhunter/candidate/index.ts +155 -0
- package/skeleton/src/common/libs/headhunter/mission/index.ts +30 -0
- package/skeleton/src/common/libs/hub/index.ts +41 -0
- package/skeleton/src/server/config/communication.ts +48 -0
- package/skeleton/src/server/config/crosspath.ts +9 -0
- package/skeleton/src/server/config/data.ts +34 -0
- package/skeleton/src/server/config/database.ts +26 -0
- package/skeleton/src/server/config/internal.ts +21 -0
- package/skeleton/src/server/config/user.ts +90 -0
- package/skeleton/src/server/index.ts +111 -23
- package/skeleton/src/server/libs/utils/slug.ts +11 -0
- package/skeleton/src/server/routes/global.ts +33 -0
- package/skeleton/src/server/routes/headhunters.ts +24 -0
- package/skeleton/src/server/routes/missions.ts +50 -0
- package/skeleton/src/server/services/Headhunter/index.ts +127 -0
- package/skeleton/src/server/services/Headhunter/service.json +6 -0
- package/skeleton/src/server/services/Mission/index.ts +174 -0
- package/skeleton/src/server/services/Mission/service.json +6 -0
- package/skeleton/src/server/services/email/sendgrid/index.ts +97 -0
- package/skeleton/src/server/services/email/sendgrid/service.json +6 -0
- package/skeleton/src/server/services/slack/index.ts +105 -0
- package/skeleton/src/server/services/slack/service.json +6 -0
- package/skeleton/src/server/services/users/index.ts +133 -0
- package/skeleton/src/server/services/users/service.json +6 -0
- package/skeleton/src/server/tsconfig.json +6 -8
- package/skeleton/var/typings/routes.d.ts +541 -0
- package/src/compiler/common/babel/index.ts +28 -25
- package/src/index.ts +1 -1
- package/src/utils/keyboard.ts +1 -1
- package/skeleton/package-lock.json +0 -6139
- package/skeleton/src/client/components/LoginModal.tsx +0 -45
- package/skeleton/src/client/pages/app/_layout/index.less +0 -20
- package/skeleton/src/client/pages/app/_layout/index.tsx +0 -33
- package/skeleton/src/client/pages/app/index.tsx +0 -57
- package/skeleton/src/client/pages/landing/_layout/index.less +0 -145
- package/skeleton/src/client/pages/landing/_layout/index.tsx +0 -63
- package/skeleton/src/client/pages/landing/index.tsx +0 -73
- package/skeleton/src/server/models.ts +0 -117
- package/skeleton/src/server/routes/general.ts +0 -66
- package/skeleton/src/server/services/auth/index.ts +0 -80
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/*----------------------------------
|
|
2
|
+
- DEPENDANCES
|
|
3
|
+
----------------------------------*/
|
|
4
|
+
|
|
5
|
+
// npm
|
|
6
|
+
import { WebClient } from '@slack/web-api';
|
|
7
|
+
|
|
8
|
+
// App
|
|
9
|
+
import { Environment } from '@app';
|
|
10
|
+
|
|
11
|
+
// Core
|
|
12
|
+
import Service from '@server/app/service';
|
|
13
|
+
|
|
14
|
+
/*----------------------------------
|
|
15
|
+
- SERVICE CONFIG
|
|
16
|
+
----------------------------------*/
|
|
17
|
+
|
|
18
|
+
const LogPrefix = `[slack]`;
|
|
19
|
+
|
|
20
|
+
export type Config = {
|
|
21
|
+
token: string,
|
|
22
|
+
channels: {
|
|
23
|
+
default: string
|
|
24
|
+
} & {
|
|
25
|
+
[channelName: string]: string
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type Hook = {
|
|
30
|
+
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export type Subservices = {
|
|
34
|
+
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/*----------------------------------
|
|
38
|
+
- TYPES
|
|
39
|
+
----------------------------------*/
|
|
40
|
+
|
|
41
|
+
/*----------------------------------
|
|
42
|
+
- SERVICE
|
|
43
|
+
----------------------------------*/
|
|
44
|
+
export default class SlackService<TConfig extends Config = Config>
|
|
45
|
+
extends Service<TConfig, Hook, CrossPath, Subservices> {
|
|
46
|
+
|
|
47
|
+
private api = new WebClient(this.config.token);
|
|
48
|
+
|
|
49
|
+
/*----------------------------------
|
|
50
|
+
- LIFECYCLE
|
|
51
|
+
----------------------------------*/
|
|
52
|
+
|
|
53
|
+
public async start() {
|
|
54
|
+
|
|
55
|
+
if (Environment.profile === 'prod')
|
|
56
|
+
this.sendInChannel('default', `The CrossPath CSM server (${Environment.profile}) has successfully started :partying_face:`);
|
|
57
|
+
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
public async ready() {
|
|
61
|
+
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
public async shutdown() {
|
|
65
|
+
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/*----------------------------------
|
|
69
|
+
- ACTIONS
|
|
70
|
+
----------------------------------*/
|
|
71
|
+
public async sendInChannel( channelName: keyof typeof this.config.channels, message: string ) {
|
|
72
|
+
|
|
73
|
+
if (this.api === undefined) {
|
|
74
|
+
console.error(LogPrefix, `Slack web api not initialized. It can be because the api token has not been loaded.`);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
console.info(LogPrefix, `Sending message to slack, channel: ${channelName}. Message:\n${message}`);
|
|
79
|
+
|
|
80
|
+
const channelId = this.config.channels[channelName];
|
|
81
|
+
|
|
82
|
+
await this.api.chat.postMessage({
|
|
83
|
+
channel: channelId,
|
|
84
|
+
text: message,
|
|
85
|
+
mrkdwn: true,
|
|
86
|
+
link_names: true
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
public async sendToUser( userId: string, message: string ) {
|
|
91
|
+
|
|
92
|
+
if (this.api === undefined) {
|
|
93
|
+
console.error(LogPrefix, `Slack web api not initialized. It can be because the api token has not been loaded.`);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
await this.api.chat.postMessage({
|
|
98
|
+
channel: userId,
|
|
99
|
+
text: message,
|
|
100
|
+
mrkdwn: true,
|
|
101
|
+
link_names: true ,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/*----------------------------------
|
|
2
|
+
- DEPENDANCES
|
|
3
|
+
----------------------------------*/
|
|
4
|
+
|
|
5
|
+
// npm
|
|
6
|
+
import sha1 from 'sha1';
|
|
7
|
+
import hInterval from 'human-interval';
|
|
8
|
+
|
|
9
|
+
// Core
|
|
10
|
+
import type { Request as ServerRequest } from '@server/services/router';
|
|
11
|
+
import jsonMask from '@server/services/router/response/mask';
|
|
12
|
+
|
|
13
|
+
// App
|
|
14
|
+
import { SQL, AES } from '@app';
|
|
15
|
+
import { InternalCollaborator } from '@/server/models';
|
|
16
|
+
import UsersManagementService, { THttpRequest } from '@server/services/users';
|
|
17
|
+
import { Forbidden } from '@common/errors';
|
|
18
|
+
|
|
19
|
+
/*----------------------------------
|
|
20
|
+
- CONFIG
|
|
21
|
+
----------------------------------*/
|
|
22
|
+
|
|
23
|
+
const ssrMask = `
|
|
24
|
+
firstName
|
|
25
|
+
name
|
|
26
|
+
`
|
|
27
|
+
|
|
28
|
+
/*----------------------------------
|
|
29
|
+
- TYPES
|
|
30
|
+
----------------------------------*/
|
|
31
|
+
|
|
32
|
+
export type User = InternalCollaborator
|
|
33
|
+
|
|
34
|
+
type TJwtSession = {
|
|
35
|
+
email: string
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/*----------------------------------
|
|
39
|
+
- SERVICE
|
|
40
|
+
----------------------------------*/
|
|
41
|
+
export default class UsersManagement extends UsersManagementService<User, CrossPathCSM, TJwtSession> {
|
|
42
|
+
|
|
43
|
+
protected displayName(user?: User | null) {
|
|
44
|
+
return user ? user.email : 'Guest';
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
protected displaySessionName(session: TJwtSession) {
|
|
48
|
+
return session.email;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public forSSR( request: ServerRequest ) {
|
|
52
|
+
return request.user
|
|
53
|
+
? jsonMask(request.user, ssrMask, request.user)
|
|
54
|
+
: null
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/*----------------------------------
|
|
58
|
+
- ACTIONS
|
|
59
|
+
----------------------------------*/
|
|
60
|
+
public async login( email: string, password: string, request: ServerRequest ) {
|
|
61
|
+
|
|
62
|
+
console.log(`try to login ${email} with ${password}`);
|
|
63
|
+
|
|
64
|
+
// Check password
|
|
65
|
+
const user = await SQL`
|
|
66
|
+
SELECT *
|
|
67
|
+
FROM InternalCollaborator
|
|
68
|
+
WHERE email = ${email}
|
|
69
|
+
`.first<User>();
|
|
70
|
+
|
|
71
|
+
// Account not activated yet
|
|
72
|
+
if (!user)
|
|
73
|
+
throw new Forbidden(`No account exists with this email.`);
|
|
74
|
+
|
|
75
|
+
console.log(user.airtableId, password);
|
|
76
|
+
|
|
77
|
+
// Check password
|
|
78
|
+
if (user.airtableId !== password)
|
|
79
|
+
throw new Forbidden(`Bad password`);
|
|
80
|
+
|
|
81
|
+
const token = await this.createSession({ email }, request);
|
|
82
|
+
|
|
83
|
+
return { token, user }
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
public async decodeSession( session: TJwtSession, req: THttpRequest ): Promise<User | null> {
|
|
87
|
+
|
|
88
|
+
// Email is mandatory for indentifying the sessin
|
|
89
|
+
if (!session.email) {
|
|
90
|
+
console.warn("No email provided in JWT decrypted session:", session);
|
|
91
|
+
throw new Forbidden(`Unvalid session`);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
let user = await SQL`
|
|
95
|
+
SELECT *
|
|
96
|
+
FROM InternalCollaborator
|
|
97
|
+
WHERE email = ${session.email}
|
|
98
|
+
`.first<User>();
|
|
99
|
+
|
|
100
|
+
if (!user)
|
|
101
|
+
return null;
|
|
102
|
+
|
|
103
|
+
user = {
|
|
104
|
+
...user,
|
|
105
|
+
roles: ['USER']
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return user;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
public decodeToken( token: string ) {
|
|
112
|
+
|
|
113
|
+
// Decode
|
|
114
|
+
let decoded: string;
|
|
115
|
+
try {
|
|
116
|
+
decoded = AES.decrypt('activationToken', token);
|
|
117
|
+
} catch (error) {
|
|
118
|
+
throw new Forbidden("This activation token is invalid.");
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Extract data
|
|
122
|
+
const [email, expirationTimeStr] = decoded.split('::::');
|
|
123
|
+
|
|
124
|
+
// Check expiration date
|
|
125
|
+
if (!!expirationTimeStr) {
|
|
126
|
+
const expirationTime = parseInt(expirationTimeStr);
|
|
127
|
+
if (Date.now() > expirationTime)
|
|
128
|
+
throw new Forbidden("This link has expired. Please renew your password reset request.");
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return email;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
@@ -5,18 +5,15 @@
|
|
|
5
5
|
"baseUrl": "..",
|
|
6
6
|
"paths": {
|
|
7
7
|
|
|
8
|
-
//
|
|
8
|
+
// Temp workaround because rootDir ignored in the package for type check
|
|
9
|
+
"5htp-airtable/*": ["../node_modules/5htp-airtable/src/*"],
|
|
9
10
|
|
|
11
|
+
"@/server/models": ["./server/.generated/models"],
|
|
12
|
+
|
|
10
13
|
"@client/*": ["../node_modules/5htp-core/src/client/*"],
|
|
11
14
|
"@common/*": ["../node_modules/5htp-core/src/common/*"],
|
|
12
15
|
"@server/*": ["../node_modules/5htp-core/src/server/*"],
|
|
13
16
|
|
|
14
|
-
"@validator": ["../node_modules/5htp-core/src/server/data/input"],
|
|
15
|
-
"@router": ["../node_modules/5htp-core/src/server/services/router"],
|
|
16
|
-
"@errors": ["../node_modules/5htp-core/src/common/errors"],
|
|
17
|
-
|
|
18
|
-
"@models": ["../server/models"],
|
|
19
|
-
|
|
20
17
|
"@/*": ["./*"],
|
|
21
18
|
|
|
22
19
|
// ATTENTION: Les références à preact doivent toujours pointer vers la même instance
|
|
@@ -29,6 +26,7 @@
|
|
|
29
26
|
|
|
30
27
|
"include": [
|
|
31
28
|
".",
|
|
32
|
-
"../../
|
|
29
|
+
"../../var/typings",
|
|
30
|
+
".generated/services.d.ts",
|
|
33
31
|
]
|
|
34
32
|
}
|