Skip to content

Commit e103cd5

Browse files
authored
Merge pull request #183 from VKCOM/malzhanov/ios-refactor
Ios pre-prod refactor so everything works
2 parents 4923b9d + 10072e1 commit e103cd5

File tree

47 files changed

+9747
-3606
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+9747
-3606
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,5 @@
1111
/temp/
1212
/tmp/
1313
.mypy_cache
14+
15+
idb-applications

lib/types/nsyslog-parser.d.ts

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
declare module "nsyslog-parser" {
2+
/**
3+
* Represents a single structured data entry, e.g. the objects within "structuredData".
4+
* Each of these can have a mandatory "$id" key and then any additional properties.
5+
*/
6+
export interface StructuredDataEntry {
7+
$id: string;
8+
[key: string]: string;
9+
}
10+
11+
/**
12+
* Represents the CEF (Common Event Format) details that can appear on some entries.
13+
*/
14+
export interface CefExtension {
15+
version: string; // e.g. "CEF:0"
16+
deviceVendor: string; // e.g. "security"
17+
deviceProduct: string; // e.g. "threatmanager"
18+
deviceVersion: string; // e.g. "1.0"
19+
deviceEventClassID: string; // e.g. "100"
20+
name: string; // e.g. "detected a \\| in message"
21+
severity: string; // e.g. "10"
22+
extension: string; // Raw extension string (e.g. "src=10.0.0.1 act=blocked...")
23+
}
24+
25+
/**
26+
* Represents one syslog-like message object as found in the array.
27+
* Optional fields are marked with "?". Note that some fields
28+
* can be null or empty strings when absent or unknown.
29+
*/
30+
export interface SyslogMessage {
31+
/** The full, unmodified original log line. */
32+
originalMessage: string;
33+
34+
/** Priority string if present (e.g. "<189>") or empty string. */
35+
pri?: string; // can be "" if not present
36+
/** Parsed numeric value from `pri` if present, or null if missing. */
37+
prival?: number | null;
38+
39+
/** Syslog facility as numeric value, if known. */
40+
facilityval?: number | null;
41+
/** Syslog level (severity) as numeric value, if known. */
42+
levelval?: number | null;
43+
/** Parsed facility name, if known (e.g. "auth", "local7"). */
44+
facility?: "kern" | "user" | "mail" | "daemon" | "auth" | "syslog" | "lpr" | "news" | "uucp" | "cron" | "authpriv" | "ftp" | "ntp" | "security" | "console" | "solaris" | "local0" | "local1" | "local2" | "local3" | "local4" | "local5" | "local6" | "local7" | string;
45+
/** Parsed severity/level name, if known (e.g. "crit", "notice"). */
46+
level?: "emerg" | "alert" | "crit" | "error" | "warn" | "notice" | "info" | "debug" | string;
47+
48+
/**
49+
* Syslog version (used in RFC 5424). For BSD-type or unknown messages,
50+
* this may be absent.
51+
*/
52+
version?: number;
53+
54+
/**
55+
* A string identifying the detected syslog "type". Examples: "BSD", "RFC5424", "CEF", "UNKNOWN".
56+
* In practice, you may see additional or custom strings as well.
57+
*/
58+
type: string;
59+
60+
/**
61+
* Parsed timestamp in ISO8601 format, e.g. "2019-10-11T20:14:15.000Z".
62+
* If the parser guessed one, it will be here; otherwise it may be a fallback or empty string.
63+
*/
64+
ts: string;
65+
66+
/** Hostname or IP, if found. */
67+
host?: string;
68+
/** Application name/process name, if found. */
69+
appName?: string;
70+
/** Process ID (pid) if it was found in the header, e.g. "1334" in "pinger[1334]". */
71+
pid?: string;
72+
/** RFC5424 message ID if present, e.g. "ID47". */
73+
messageid?: string;
74+
75+
/** The final extracted message portion (without the syslog header). */
76+
message?: string;
77+
78+
/**
79+
* Some log lines contain "chain"—for example, in RFC5424 with multiple hostnames
80+
* or structured references. Often an empty array.
81+
*/
82+
chain?: string[];
83+
84+
/** Free-form array for any extracted fields that did not have a dedicated property. */
85+
fields?: any[];
86+
87+
/** Syslog header portion as originally parsed (if separated). */
88+
header?: string;
89+
90+
/**
91+
* StructuredData is typically an array of objects used in RFC5424 logs.
92+
* Each object can have `$id` plus arbitrary key-value pairs.
93+
*/
94+
structuredData?: StructuredDataEntry[];
95+
96+
/**
97+
* Only present if the message is identified as CEF (Common Event Format).
98+
* Holds the parsed CEF fields (deviceVendor, deviceProduct, etc.).
99+
*/
100+
cef?: CefExtension;
101+
}
102+
export default function parse(line: string): SyslogMessage;
103+
}

lib/types/syrup.d.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
declare module "@devicefarmer/stf-syrup" {
2+
import Bluebird from "bluebird";
3+
type extractDesRet<RetT> = RetT extends SyrupI<never, never, infer RetX>
4+
? RetX
5+
: unknown;
6+
type extractBluebirdReturnR<RetT> = RetT extends Bluebird<infer RetX>
7+
? RetX
8+
: RetT;
9+
export class SyrupI<
10+
OptionsT extends object = any, // TODO: find a way to remove any. Maybe we union all the options that are needed for each dependency?
11+
DepsT extends SyrupI[] = [],
12+
RetT = unknown | void,
13+
DepsRetsT extends (unknown | void)[] = [] // TODO: maybe we can extract DepsRetsT somehow?
14+
> {
15+
constructor(options: OptionsT | null);
16+
define<
17+
BodyT extends (options: OptionsT, ...deps: DepsRetsT) => unknown
18+
>(
19+
body: BodyT
20+
): SyrupI<
21+
OptionsT,
22+
DepsT,
23+
extractBluebirdReturnR<ReturnType<typeof body>>,
24+
DepsRetsT
25+
>;
26+
dependency<DepT extends SyrupI<never, never>>(
27+
dep: DepT
28+
): SyrupI<
29+
OptionsT,
30+
[...DepsT, DepT],
31+
RetT,
32+
[...DepsRetsT, extractDesRet<DepT>]
33+
>;
34+
consume<NewOptionsT extends OptionsT>(
35+
overrides: NewOptionsT
36+
): Bluebird<RetT>;
37+
invoke(overrides: OptionsT, ...args: DepsT[]): RetT;
38+
}
39+
export type ParallelSyrup = <OptionsT extends object>(
40+
options?: OptionsT
41+
) => SyrupI;
42+
export namespace ParallelSyrup {
43+
const Syrup: SyrupI;
44+
}
45+
46+
export type SerialSyrup = ParallelSyrup;
47+
export namespace SerialSyrup {
48+
const Syrup: SyrupI;
49+
}
50+
51+
export type Syrup = ParallelSyrup;
52+
export namespace Syrup {
53+
const serial: SerialSyrup;
54+
}
55+
56+
export default Syrup;
57+
}

lib/units/api/auth.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@ export function auth(options) {
1818
})
1919
}
2020
else {
21-
// No session, forward to auth client
22-
res.redirect(options.authUrl) // TODO: remove this
23-
// res.redirect('/')
21+
res.redirect('/')
2422
}
2523
}
2624
}

lib/units/api/controllers/autotests.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as dbapi from '../../../db/api.js'
44
import datautil from '../../../util/datautil.js'
55
import deviceutil from '../../../util/deviceutil.js'
66
import wireutil from '../../../wire/util.js'
7-
import wirerouter from '../../../wire/router.js'
7+
import {WireRouter} from '../../../wire/router.js'
88
import wire from '../../../wire/index.js'
99
import {v4 as uuidv4} from 'uuid'
1010
import logger from '../../../util/logger.js'
@@ -165,7 +165,7 @@ function installOnDevice(req, res) {
165165
log.info('Installation result: Device is not responding')
166166
return apiutil.respond(res, 504, 'Device is not responding')
167167
}, apiutil.INSTALL_APK_WAIT)
168-
let messageListener = wirerouter()
168+
let messageListener = new WireRouter()
169169
.on(wire.InstallResultMessage, function(channel, message) {
170170
if (message.serial === serial) {
171171
clearTimeout(timer)
@@ -225,7 +225,7 @@ function useAndConnectDevice(req, res) {
225225
Sentry.captureMessage('504: Device is not responding (failed to join group)')
226226
return apiutil.respond(res, 504, 'Device is not responding (failed to join group)')
227227
}, apiutil.GRPC_WAIT_TIMEOUT)
228-
let useDeviceMessageListener = wirerouter()
228+
let useDeviceMessageListener = new WireRouter() // wtf?
229229
.on(wire.JoinGroupMessage, function(channel, message) {
230230
log.info(device.serial + ' added to user group ' + req.user)
231231
if (message.serial === serial && message.owner.email === req.user.email) {
@@ -240,7 +240,7 @@ function useAndConnectDevice(req, res) {
240240
Sentry.captureMessage('504: Device is not responding (failed to connect to device)')
241241
return apiutil.respond(res, 504, 'Device is not responding (failed to connect to device)')
242242
}, apiutil.GRPC_WAIT_TIMEOUT)
243-
let messageListener = wirerouter()
243+
let messageListener = new WireRouter()
244244
.on(wire.ConnectStartedMessage, function(channel, message) {
245245
if (message.serial === serial) {
246246
clearTimeout(timer)

lib/units/api/controllers/devices.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import datautil from '../../../util/datautil.js'
99
import {v4 as uuidv4} from 'uuid'
1010
import wire from '../../../wire/index.js'
1111
import wireutil from '../../../wire/util.js'
12-
import wirerouter from '../../../wire/router.js'
12+
import {WireRouter} from '../../../wire/router.js'
1313
var log = logger.createLogger('api:controllers:devices')
1414

1515
/* ------------------------------------ PRIVATE FUNCTIONS ------------------------------- */
@@ -355,7 +355,7 @@ function addOriginGroupDevices(req, res) {
355355
apiutil.respond(res, 504, 'Gateway Time-out')
356356
reject('timeout')
357357
}, apiutil.GRPC_WAIT_TIMEOUT)
358-
messageListener = wirerouter()
358+
messageListener = new WireRouter()
359359
.on(wire.DeviceOriginGroupMessage, function(channel, message) {
360360
if (message.signature === signature) {
361361
clearTimeout(responseTimer)

lib/units/api/controllers/user.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import datautil from '../../../util/datautil.js'
88
import deviceutil from '../../../util/deviceutil.js'
99
import wire from '../../../wire/index.js'
1010
import wireutil from '../../../wire/util.js'
11-
import wirerouter from '../../../wire/router.js'
11+
import {WireRouter} from '../../../wire/router.js'
1212
import * as apiutil from '../../../util/apiutil.js'
1313
import * as jwtutil from '../../../util/jwtutil.js'
1414
import * as lockutil from '../../../util/lockutil.js'
@@ -125,7 +125,7 @@ function addUserDevice(req, res) {
125125
req.options.channelRouter.removeListener(wireutil.global, messageListener)
126126
return apiutil.respond(res, 504, 'Device is not responding')
127127
}, apiutil.GRPC_WAIT_TIMEOUT)
128-
let messageListener = wirerouter()
128+
let messageListener = new WireRouter()
129129
.on(wire.JoinGroupMessage, function(channel, message) {
130130
log.info(device.serial + ' added to user group ' + req.user)
131131
if (message.serial === serial && message.owner.email === req.user.email) {
@@ -211,7 +211,7 @@ function deleteUserDeviceBySerial(req, res) {
211211
return apiutil.respond(res, 504, 'Device is not responding')
212212
}
213213
}, apiutil.GRPC_WAIT_TIMEOUT)
214-
var messageListener = wirerouter()
214+
var messageListener = new WireRouter()
215215
.on(wire.LeaveGroupMessage, function(channel, message) {
216216
if (message.serial === serial &&
217217
(message.owner.email === req.user.email || req.user.privilege === 'admin')) {
@@ -283,7 +283,7 @@ function remoteConnectUserDeviceBySerial(req, res) {
283283
req.options.sub.unsubscribe(responseChannel)
284284
return apiutil.respond(res, 504, 'Device is not responding')
285285
}, apiutil.GRPC_WAIT_TIMEOUT)
286-
let messageListener = wirerouter()
286+
let messageListener = new WireRouter()
287287
.on(wire.ConnectStartedMessage, function(channel, message) {
288288
if (message.serial === serial) {
289289
clearTimeout(timer)
@@ -356,7 +356,7 @@ function remoteDisconnectUserDeviceBySerial(req, res) {
356356
return apiutil.respond(res, 504, 'Device is not responding')
357357
}
358358
}, apiutil.GRPC_WAIT_TIMEOUT)
359-
var messageListener = wirerouter()
359+
var messageListener = new WireRouter()
360360
.on(wire.ConnectStoppedMessage, function(channel, message) {
361361
if (message.serial === serial) {
362362
clearTimeout(timer)

lib/units/api/helpers/securityHandlers.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ async function accessTokenAuth(req) {
2828
log.error('Bad Access Token Header or missed cookie')
2929
throw {
3030
status: 401
31-
, message: 'Bad Credentials'
31+
, message: 'No Credentials'
3232
}
3333
}
3434
try {
@@ -47,6 +47,12 @@ async function accessTokenAuth(req) {
4747
}
4848
data = jwtutil.decode(token.jwt, req.options.secret)
4949
}
50+
if (data === null) {
51+
throw {
52+
status: 401
53+
, message: 'Bad token'
54+
}
55+
}
5056
const user = await dbapi.loadUser(data.email)
5157
if (user) {
5258
if (user.privilege === apiutil.USER && operationTag.indexOf('admin') > -1) {

lib/units/base-device/support/router.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import syrup from '@devicefarmer/stf-syrup'
2-
import wirerouter from '../../../wire/router.js'
2+
import {WireRouter} from '../../../wire/router.js'
33
import sub from './sub.js'
44
import channels from './channels.js'
55
export default syrup.serial()
66
.dependency(sub)
77
.dependency(channels)
88
.define((options, sub, channels) => {
9-
let router = wirerouter()
9+
let router = new WireRouter()
1010
sub.on('message', router.handler())
1111
// Special case, we're hooking into a message that's not actually routed.
1212
router.on({$code: 'message'}, channel => {

lib/units/base-device/support/storage.js

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,39 +7,41 @@ import logger from '../../../util/logger.js'
77
export default syrup.serial()
88
.define(options => {
99
const log = logger.createLogger('device:support:storage')
10-
let plugin = Object.create(null)
11-
plugin.store = function(type, stream, meta) {
12-
let resolver = Promise.defer()
13-
let args = {
14-
url: url.resolve(options.storageUrl, util.format('s/upload/%s', type))
15-
, headers: {
16-
internal: 'Internal ' + meta.jwt
17-
}
18-
}
19-
let req = request.post(args, function(err, res, body) {
20-
if (err) {
21-
log.error('Upload to "%s" failed', args.url, err.stack)
22-
resolver.reject(err)
23-
}
24-
else if (res.statusCode !== 201) {
25-
log.error('Upload to "%s" failed: HTTP %d', args.url, res.statusCode)
26-
resolver.reject(new Error(util.format('Upload to "%s" failed: HTTP %d', args.url, res.statusCode)))
27-
}
28-
else {
29-
try {
30-
let result = JSON.parse(body)
31-
log.info('Uploaded to "%s"', result.resources.file.href)
32-
resolver.resolve(result.resources.file)
10+
let plugin = {
11+
store: function(type, stream, meta) {
12+
let resolver = Promise.defer()
13+
let args = {
14+
url: url.resolve(options.storageUrl, util.format('s/upload/%s', type))
15+
, headers: {
16+
internal: 'Internal ' + meta.jwt
3317
}
34-
catch (err) {
35-
log.error('Invalid JSON in response', err.stack, body)
18+
}
19+
let req = request.post(args, function(err, res, body) {
20+
if (err) {
21+
log.error('Upload to "%s" failed', args.url, err.stack)
3622
resolver.reject(err)
3723
}
38-
}
39-
})
40-
req.form()
41-
.append('file', stream, meta)
42-
return resolver.promise
24+
else if (res.statusCode !== 201) {
25+
log.error('Upload to "%s" failed: HTTP %d', args.url, res.statusCode)
26+
log.debug(body)
27+
resolver.reject(new Error(util.format('Upload to "%s" failed: HTTP %d', args.url, res.statusCode)))
28+
}
29+
else {
30+
try {
31+
let result = JSON.parse(body)
32+
log.info('Uploaded to "%s"', result.resources.file.href)
33+
resolver.resolve(result.resources.file)
34+
}
35+
catch (err) {
36+
log.error('Invalid JSON in response', err.stack, body)
37+
resolver.reject(err)
38+
}
39+
}
40+
})
41+
req.form()
42+
.append('file', stream, meta)
43+
return resolver.promise
44+
}
4345
}
4446
return plugin
4547
})

0 commit comments

Comments
 (0)