chore(hooks): turn on prettier hook for typescript

This commit is contained in:
Phil Booth 2019-08-16 07:12:35 +01:00
Родитель 8d087d850d
Коммит 7e69761f05
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 36FBB106F9C32516
9 изменённых файлов: 108 добавлений и 94 удалений

Просмотреть файл

@ -74,6 +74,10 @@
"prettier --write", "prettier --write",
"git add" "git add"
], ],
"*.ts": [
"prettier --write",
"git add"
],
"*.css": [ "*.css": [
"prettier --write", "prettier --write",
"git add" "git add"

Просмотреть файл

@ -1,12 +1,9 @@
{ {
"extends": [ "extends": ["tslint:recommended", "tslint-config-prettier"],
"tslint:recommended", "rulesDirectory": ["tslint-plugin-prettier"],
"tslint-config-prettier" "rules": {
], "interface-name": [true, "never-prefix"],
"rulesDirectory": ["tslint-plugin-prettier"], "interface-over-type-literal": false,
"rules": { "prettier": [true, ".prettierrc"]
"interface-name": [true, "never-prefix"], }
"interface-over-type-literal": false,
"prettier": [true, ".prettierrc"]
}
} }

Просмотреть файл

@ -1,11 +1,7 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "es5", "target": "es5",
"lib": [ "lib": ["dom", "dom.iterable", "esnext"],
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true, "allowJs": true,
"skipLibCheck": true, "skipLibCheck": true,
"esModuleInterop": true, "esModuleInterop": true,
@ -19,7 +15,5 @@
"noEmit": true, "noEmit": true,
"jsx": "preserve" "jsx": "preserve"
}, },
"include": [ "include": ["src"]
"src"
]
} }

Просмотреть файл

@ -11,61 +11,61 @@ const conf = convict({
default: 'oidc-claim-id-token-email', default: 'oidc-claim-id-token-email',
doc: 'Authentication header that should be logged for the user', doc: 'Authentication header that should be logged for the user',
env: 'AUTH_HEADER', env: 'AUTH_HEADER',
format: String format: String,
}, },
authdbUrl: { authdbUrl: {
default: 'http://localhost:8000', default: 'http://localhost:8000',
doc: 'fxa-auth-db-mysql url', doc: 'fxa-auth-db-mysql url',
env: 'AUTHDB_URL', env: 'AUTHDB_URL',
format: String format: String,
}, },
env: { env: {
default: 'production', default: 'production',
doc: 'The current node.js environment', doc: 'The current node.js environment',
env: 'NODE_ENV', env: 'NODE_ENV',
format: ['development', 'stage', 'production'] format: ['development', 'stage', 'production'],
}, },
listen: { listen: {
host: { host: {
default: '127.0.0.1', default: '127.0.0.1',
doc: 'The ip address the server should bind', doc: 'The ip address the server should bind',
env: 'IP_ADDRESS', env: 'IP_ADDRESS',
format: 'ipaddress' format: 'ipaddress',
}, },
port: { port: {
default: 7100, default: 7100,
doc: 'The port the server should bind', doc: 'The port the server should bind',
env: 'PORT', env: 'PORT',
format: 'port' format: 'port',
}, },
publicUrl: { publicUrl: {
default: 'http://127.0.0.1:3031', default: 'http://127.0.0.1:3031',
env: 'PUBLIC_URL', env: 'PUBLIC_URL',
format: 'url' format: 'url',
} },
}, },
logging: { logging: {
app: { default: 'fxa-support-panel' }, app: { default: 'fxa-support-panel' },
fmt: { fmt: {
default: 'heka', default: 'heka',
env: 'LOGGING_FORMAT', env: 'LOGGING_FORMAT',
format: ['heka', 'pretty'] format: ['heka', 'pretty'],
}, },
level: { level: {
default: 'info', default: 'info',
env: 'LOG_LEVEL' env: 'LOG_LEVEL',
}, },
routes: { routes: {
enabled: { enabled: {
default: true, default: true,
doc: 'Enable route logging. Set to false to trimming CI logs.', doc: 'Enable route logging. Set to false to trimming CI logs.',
env: 'ENABLE_ROUTE_LOGGING' env: 'ENABLE_ROUTE_LOGGING',
}, },
format: { format: {
default: 'default_fxa', default: 'default_fxa',
format: ['default_fxa', 'dev_fxa', 'default', 'dev', 'short', 'tiny'] format: ['default_fxa', 'dev_fxa', 'default', 'dev', 'short', 'tiny'],
} },
} },
}, },
security: { security: {
csp: { csp: {
@ -73,10 +73,10 @@ const conf = convict({
default: 'none', default: 'none',
doc: doc:
'https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors', 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors',
env: 'CSP_FRAME_ANCESTORS' env: 'CSP_FRAME_ANCESTORS',
} },
} },
} },
}); });
// handle configuration files. you can specify a CSV list of configuration // handle configuration files. you can specify a CSV list of configuration

Просмотреть файл

@ -29,7 +29,7 @@ const queryValidator = joi
.string() .string()
.required() .required()
.hex() .hex()
.length(32) .length(32),
}) })
.required(); .required();
@ -95,22 +95,31 @@ class SupportController {
const uid = query.uid; const uid = query.uid;
const requestTicket = query.requestTicket || 'ticket-unknown'; const requestTicket = query.requestTicket || 'ticket-unknown';
const opts = { const opts = {
json: true json: true,
}; };
// This is the user who is asking for the information: // This is the user who is asking for the information:
this.logger.info('infoRequest', { this.logger.info('infoRequest', {
authUser: request.headers[this.config.authHeader.toLowerCase()], authUser: request.headers[this.config.authHeader.toLowerCase()],
requestTicket, requestTicket,
uid uid,
}); });
let account: AccountResponse; let account: AccountResponse;
let devices: DevicesResponse; let devices: DevicesResponse;
let subscriptions: SubscriptionResponse; let subscriptions: SubscriptionResponse;
try { try {
[account, devices, subscriptions] = await P.all([ [account, devices, subscriptions] = await P.all([
requests.get({ ...opts, url: `${this.config.authdbUrl}/account/${uid}` }), requests.get({
requests.get({ ...opts, url: `${this.config.authdbUrl}/account/${uid}/devices` }), ...opts,
requests.get({ ...opts, url: `${this.config.authdbUrl}/account/${uid}/subscriptions` }) url: `${this.config.authdbUrl}/account/${uid}`,
}),
requests.get({
...opts,
url: `${this.config.authdbUrl}/account/${uid}/devices`,
}),
requests.get({
...opts,
url: `${this.config.authdbUrl}/account/${uid}/subscriptions`,
}),
]); ]);
} catch (err) { } catch (err) {
this.logger.error('infoFetch', { err }); this.logger.error('infoFetch', { err });
@ -122,7 +131,7 @@ class SupportController {
totpResponse = await requests.get({ totpResponse = await requests.get({
json: true, json: true,
resolveWithFullResponse: true, resolveWithFullResponse: true,
url: `${this.config.authdbUrl}/totp/${uid}` url: `${this.config.authdbUrl}/totp/${uid}`,
}); });
totpEnabled = (totpResponse.body as TotpTokenResponse).enabled; totpEnabled = (totpResponse.body as TotpTokenResponse).enabled;
} catch (err) { } catch (err) {
@ -137,21 +146,29 @@ class SupportController {
const context: PanelTemplateContext = { const context: PanelTemplateContext = {
created: String(new Date(account.createdAt)), created: String(new Date(account.createdAt)),
devices: devices.map(d => { devices: devices.map(d => {
return { name: d.name, type: d.type, created: String(new Date(d.createdAt)) }; return {
created: String(new Date(d.createdAt)),
name: d.name,
type: d.type,
};
}), }),
email: account.email, email: account.email,
emailVerified: !!account.emailVerified, emailVerified: !!account.emailVerified,
locale: account.locale, locale: account.locale,
subscriptionStatus: hasSubscriptions, subscriptionStatus: hasSubscriptions,
twoFactorAuth: totpEnabled, twoFactorAuth: totpEnabled,
uid uid,
}; };
const payload = this.template(context); const payload = this.template(context);
return h.response(payload).code(200); return h.response(payload).code(200);
} }
} }
export function init(logger: Logger, config: SupportConfig, server: hapi.Server) { export function init(
logger: Logger,
config: SupportConfig,
server: hapi.Server
) {
let rootDir; let rootDir;
// Check to see if we're running in a compiled form for prod/dev or testing // Check to see if we're running in a compiled form for prod/dev or testing
if (__dirname.includes('/dist/')) { if (__dirname.includes('/dist/')) {
@ -163,7 +180,7 @@ export function init(logger: Logger, config: SupportConfig, server: hapi.Server)
} }
const templateDir = path.join(rootDir, 'lib', 'templates'); const templateDir = path.join(rootDir, 'lib', 'templates');
const pageTemplate = fs.readFileSync(path.join(templateDir, 'index.html'), { const pageTemplate = fs.readFileSync(path.join(templateDir, 'index.html'), {
encoding: 'UTF-8' encoding: 'UTF-8',
}); });
const template = handlebars.compile(pageTemplate); const template = handlebars.compile(pageTemplate);
@ -174,17 +191,17 @@ export function init(logger: Logger, config: SupportConfig, server: hapi.Server)
{ {
handler: supportController.heartbeat, handler: supportController.heartbeat,
method: 'GET', method: 'GET',
path: '/__lbheartbeat__' path: '/__lbheartbeat__',
}, },
{ {
method: 'GET', method: 'GET',
options: { options: {
handler: supportController.displayUser, handler: supportController.displayUser,
validate: { validate: {
query: queryValidator as hapiJoi.ObjectSchema query: queryValidator as hapiJoi.ObjectSchema,
} },
}, },
path: '/' path: '/',
} },
]); ]);
} }

Просмотреть файл

@ -20,7 +20,10 @@ export type ServerConfig = api.SupportConfig & {
}; };
}; };
export async function init(serverConfig: ServerConfig, logger: Logger): Promise<hapi.Server> { export async function init(
serverConfig: ServerConfig,
logger: Logger
): Promise<hapi.Server> {
const server = new hapi.Server({ const server = new hapi.Server({
debug: serverConfig.env === 'production' ? false : { request: ['error'] }, debug: serverConfig.env === 'production' ? false : { request: ['error'] },
host: serverConfig.listen.host, host: serverConfig.listen.host,
@ -30,19 +33,19 @@ export async function init(serverConfig: ServerConfig, logger: Logger): Promise<
hsts: { hsts: {
includeSubDomains: true, includeSubDomains: true,
maxAge: 31536000, maxAge: 31536000,
preload: false preload: false,
}, },
xss: true xss: true,
} },
} },
}); });
await server.register([ await server.register([
Scooter, Scooter,
{ {
options: Config.get('security.csp'), options: Config.get('security.csp'),
plugin: Blankie plugin: Blankie,
} },
]); ]);
api.init(logger, serverConfig, server); api.init(logger, serverConfig, server);

Просмотреть файл

@ -16,7 +16,7 @@ import {
AccountResponse, AccountResponse,
DevicesResponse, DevicesResponse,
SubscriptionResponse, SubscriptionResponse,
TotpTokenResponse TotpTokenResponse,
} from '../../lib/api'; } from '../../lib/api';
import * as supportServer from '../../lib/server'; import * as supportServer from '../../lib/server';
@ -42,27 +42,27 @@ function createDefaults(): MockCallsResponse {
createdAt: now, createdAt: now,
email: 'test@example.com', email: 'test@example.com',
emailVerified: true, emailVerified: true,
locale: 'en-us' locale: 'en-us',
}, },
status: 200 status: 200,
}, },
devices: { devices: {
response: [], response: [],
status: 200 status: 200,
}, },
subscriptions: { subscriptions: {
response: [], response: [],
status: 200 status: 200,
}, },
totp: { totp: {
response: { response: {
enabled: true, enabled: true,
epoch: now, epoch: now,
sharedSecret: '', sharedSecret: '',
verified: true verified: true,
}, },
status: 200 status: 200,
} },
}; };
} }
@ -95,8 +95,8 @@ describe('Support Controller', () => {
env: 'development', env: 'development',
listen: { listen: {
host: 'localhost', host: 'localhost',
port: 8099 port: 8099,
} },
}, },
logger logger
); );
@ -111,7 +111,7 @@ describe('Support Controller', () => {
it('has a heartbeat', async () => { it('has a heartbeat', async () => {
const result = await server.inject({ const result = await server.inject({
method: 'GET', method: 'GET',
url: '/__lbheartbeat__' url: '/__lbheartbeat__',
}); });
cassert.equal(result.statusCode, 200); cassert.equal(result.statusCode, 200);
}); });
@ -124,10 +124,10 @@ describe('Support Controller', () => {
const getWithUrl = (url: string): Promise<hapi.ServerInjectResponse> => { const getWithUrl = (url: string): Promise<hapi.ServerInjectResponse> => {
return server.inject({ return server.inject({
headers: { headers: {
testing: 'example@example.com' testing: 'example@example.com',
}, },
method: 'GET', method: 'GET',
url url,
}); });
}; };
@ -160,7 +160,9 @@ describe('Support Controller', () => {
}); });
it('rejects a uid that is too long', async () => { it('rejects a uid that is too long', async () => {
const result = await getWithUrl('/?uid=4a0f70e0e32a435e8066d353e8577d22a'); const result = await getWithUrl(
'/?uid=4a0f70e0e32a435e8066d353e8577d22a'
);
cassert.equal(result.statusCode, 400); cassert.equal(result.statusCode, 400);
assertValidateErrorMessage(result.payload); assertValidateErrorMessage(result.payload);
}); });
@ -198,10 +200,10 @@ describe('Support Controller', () => {
mockCalls(createDefaults()); mockCalls(createDefaults());
const result = await server.inject({ const result = await server.inject({
headers: { headers: {
testing: 'example@example.com' testing: 'example@example.com',
}, },
method: 'GET', method: 'GET',
url: `/?uid=${uid}` url: `/?uid=${uid}`,
}); });
cassert.equal(result.statusCode, 200); cassert.equal(result.statusCode, 200);
const calls = (logger.info as SinonSpy).getCalls(); const calls = (logger.info as SinonSpy).getCalls();
@ -211,8 +213,8 @@ describe('Support Controller', () => {
{ {
authUser: 'example@example.com', authUser: 'example@example.com',
requestTicket: 'ticket-unknown', requestTicket: 'ticket-unknown',
uid: '4a0f70e0e32a435e8066d353e8577d2a' uid: '4a0f70e0e32a435e8066d353e8577d2a',
} },
]); ]);
}); });
@ -222,7 +224,7 @@ describe('Support Controller', () => {
mockCalls(defaults); mockCalls(defaults);
let result = await server.inject({ let result = await server.inject({
method: 'GET', method: 'GET',
url: `/?uid=${uid}` url: `/?uid=${uid}`,
}); });
cassert.equal(result.statusCode, 500); cassert.equal(result.statusCode, 500);
@ -232,7 +234,7 @@ describe('Support Controller', () => {
mockCalls(defaults); mockCalls(defaults);
result = await server.inject({ result = await server.inject({
method: 'GET', method: 'GET',
url: `/?uid=${uid}` url: `/?uid=${uid}`,
}); });
cassert.equal(result.statusCode, 500); cassert.equal(result.statusCode, 500);
}); });
@ -243,10 +245,12 @@ describe('Support Controller', () => {
mockCalls(defaults); mockCalls(defaults);
const result = await server.inject({ const result = await server.inject({
method: 'GET', method: 'GET',
url: `/?uid=${uid}` url: `/?uid=${uid}`,
}); });
cassert.equal(result.statusCode, 200); cassert.equal(result.statusCode, 200);
const payloadMatch = result.payload.match(/2FA enabled\?<\/th>\s*<td>\s*no/g); const payloadMatch = result.payload.match(
/2FA enabled\?<\/th>\s*<td>\s*no/g
);
cassert.isTrue(payloadMatch && payloadMatch.length === 1); cassert.isTrue(payloadMatch && payloadMatch.length === 1);
}); });
@ -256,7 +260,7 @@ describe('Support Controller', () => {
mockCalls(defaults); mockCalls(defaults);
const result = await server.inject({ const result = await server.inject({
method: 'GET', method: 'GET',
url: `/?uid=${uid}` url: `/?uid=${uid}`,
}); });
cassert.equal(result.statusCode, 500); cassert.equal(result.statusCode, 500);
}); });

Просмотреть файл

@ -18,7 +18,5 @@
"./test/**/*", "./test/**/*",
"./types/**/*" "./types/**/*"
], ],
"exclude": [ "exclude": ["node_modules"]
"node_modules"
]
} }

Просмотреть файл

@ -1,12 +1,9 @@
{ {
"extends": [ "extends": ["tslint:recommended", "tslint-config-prettier"],
"tslint:recommended", "rulesDirectory": ["tslint-plugin-prettier"],
"tslint-config-prettier" "rules": {
], "interface-name": [true, "never-prefix"],
"rulesDirectory": ["tslint-plugin-prettier"], "interface-over-type-literal": false,
"rules": { "prettier": [true, ".prettierrc"]
"interface-name": [true, "never-prefix"], }
"interface-over-type-literal": false,
"prettier": [true, ".prettierrc"]
}
} }