Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .swift-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6.0.3
6.0.3
5 changes: 5 additions & 0 deletions api/Sources/Api/Configure/router.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ public extension Configure {
use: DashboardTsCodegenRoute.handler(_:)
)

app.get(
"admin-ts-codegen",
use: AdminTsCodegenRoute.handler(_:)
)

app.post(
"site-forms",
use: SiteFormsRoute.handler(_:)
Expand Down
164 changes: 83 additions & 81 deletions api/Sources/Api/PairQL/SuperAdmin/QueryAdmins.swift
Original file line number Diff line number Diff line change
Expand Up @@ -152,87 +152,89 @@ func osVersionName(_ osVersion: Semver?) -> String? {

struct AdminQuery: CustomQueryable {
static func query(bindings: [Postgres.Data]) -> SQL.Statement {
.init("""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's some noise in these diffs that i don't understand... can you check that you're on swiftformat --version of exactly 0.55.5? if not, can you get on that version and reformat?

SELECT
parent.parents.id AS admin_id,
parent.parents.email,
parent.parents.gclid IS NOT NULL AS has_gclid,
parent.parents.subscription_id,
parent.parents.subscription_status,
parent.parents.ab_test_variant,
parent.parents.created_at AS admin_created_at,
COUNT(DISTINCT parent.keychains.id) AS num_keychains,
COALESCE(an.num_notifications, 0) AS num_notifications,
parent.children.id AS user_id,
parent.children.name as user_name,
parent.children.keylogging_enabled,
parent.children.screenshots_enabled,
COALESCE(screenshot_count, 0) AS screenshot_count,
COALESCE(keystroke_count, 0) AS keystroke_count,
COUNT(DISTINCT child.keychains.keychain_id) AS user_keychain_count,
COUNT(DISTINCT CASE WHEN parent.keys.deleted_at IS NULL THEN parent.keys.id END) AS num_keys,
child.computer_users.numeric_id,
child.computer_users.app_version,
child.computer_users.created_at AS user_device_created_at,
child.computer_users.id AS user_device_id,
parent.children.created_at AS user_created_at,
parent.computers.filter_version,
parent.computers.model_identifier,
parent.computers.app_release_channel,
parent.computers.os_version,
parent.computers.id AS device_id
FROM parent.parents
LEFT JOIN parent.keychains ON parent.parents.id = parent.keychains.parent_id
LEFT JOIN (
SELECT parent_id, COUNT(DISTINCT id) AS num_notifications
FROM parent.notifications
GROUP BY parent_id
) AS an ON parent.parents.id = an.parent_id
LEFT JOIN parent.children ON parent.parents.id = parent.children.parent_id
LEFT JOIN (
SELECT ud.child_id, COUNT(DISTINCT s.id) AS screenshot_count
FROM macapp.screenshots s
JOIN child.computer_users ud ON s.computer_user_id = ud.id
WHERE s.deleted_at IS NULL
GROUP BY ud.child_id
) AS s ON parent.children.id = s.child_id
LEFT JOIN (
SELECT ud.child_id, COUNT(DISTINCT kl.id) AS keystroke_count
FROM macapp.keystroke_lines kl
JOIN child.computer_users ud ON kl.computer_user_id = ud.id
WHERE kl.deleted_at IS NULL
GROUP BY ud.child_id
) AS k ON parent.children.id = k.child_id
LEFT JOIN child.computer_users ON parent.children.id = child.computer_users.child_id
LEFT JOIN parent.computers ON child.computer_users.computer_id = parent.computers.id
LEFT JOIN child.keychains ON parent.children.id = child.keychains.child_id
LEFT JOIN parent.keys ON child.keychains.keychain_id = parent.keys.keychain_id
WHERE
parent.parents.email NOT LIKE '%.smoke-test-%'
GROUP BY
parent.parents.id,
parent.parents.email,
parent.parents.subscription_id,
parent.parents.subscription_status,
parent.parents.created_at,
parent.children.id,
parent.children.name,
parent.children.keylogging_enabled,
parent.children.screenshots_enabled,
an.num_notifications,
screenshot_count,
keystroke_count,
child.computer_users.numeric_id,
child.computer_users.app_version,
child.computer_users.created_at,
child.computer_users.id,
parent.children.created_at,
parent.computers.filter_version,
parent.computers.model_identifier,
parent.computers.app_release_channel,
parent.computers.os_version,
parent.computers.id;
""")
.init(
"""
SELECT
parent.parents.id AS admin_id,
parent.parents.email,
parent.parents.gclid IS NOT NULL AS has_gclid,
parent.parents.subscription_id,
parent.parents.subscription_status,
parent.parents.ab_test_variant,
parent.parents.created_at AS admin_created_at,
COUNT(DISTINCT parent.keychains.id) AS num_keychains,
COALESCE(an.num_notifications, 0) AS num_notifications,
parent.children.id AS user_id,
parent.children.name as user_name,
parent.children.keylogging_enabled,
parent.children.screenshots_enabled,
COALESCE(screenshot_count, 0) AS screenshot_count,
COALESCE(keystroke_count, 0) AS keystroke_count,
COUNT(DISTINCT child.keychains.keychain_id) AS user_keychain_count,
COUNT(DISTINCT CASE WHEN parent.keys.deleted_at IS NULL THEN parent.keys.id END) AS num_keys,
child.computer_users.numeric_id,
child.computer_users.app_version,
child.computer_users.created_at AS user_device_created_at,
child.computer_users.id AS user_device_id,
parent.children.created_at AS user_created_at,
parent.computers.filter_version,
parent.computers.model_identifier,
parent.computers.app_release_channel,
parent.computers.os_version,
parent.computers.id AS device_id
FROM parent.parents
LEFT JOIN parent.keychains ON parent.parents.id = parent.keychains.parent_id
LEFT JOIN (
SELECT parent_id, COUNT(DISTINCT id) AS num_notifications
FROM parent.notifications
GROUP BY parent_id
) AS an ON parent.parents.id = an.parent_id
LEFT JOIN parent.children ON parent.parents.id = parent.children.parent_id
LEFT JOIN (
SELECT ud.child_id, COUNT(DISTINCT s.id) AS screenshot_count
FROM macapp.screenshots s
JOIN child.computer_users ud ON s.computer_user_id = ud.id
WHERE s.deleted_at IS NULL
GROUP BY ud.child_id
) AS s ON parent.children.id = s.child_id
LEFT JOIN (
SELECT ud.child_id, COUNT(DISTINCT kl.id) AS keystroke_count
FROM macapp.keystroke_lines kl
JOIN child.computer_users ud ON kl.computer_user_id = ud.id
WHERE kl.deleted_at IS NULL
GROUP BY ud.child_id
) AS k ON parent.children.id = k.child_id
LEFT JOIN child.computer_users ON parent.children.id = child.computer_users.child_id
LEFT JOIN parent.computers ON child.computer_users.computer_id = parent.computers.id
LEFT JOIN child.keychains ON parent.children.id = child.keychains.child_id
LEFT JOIN parent.keys ON child.keychains.keychain_id = parent.keys.keychain_id
WHERE
parent.parents.email NOT LIKE '%.smoke-test-%'
GROUP BY
parent.parents.id,
parent.parents.email,
parent.parents.subscription_id,
parent.parents.subscription_status,
parent.parents.created_at,
parent.children.id,
parent.children.name,
parent.children.keylogging_enabled,
parent.children.screenshots_enabled,
an.num_notifications,
screenshot_count,
keystroke_count,
child.computer_users.numeric_id,
child.computer_users.app_version,
child.computer_users.created_at,
child.computer_users.id,
parent.children.created_at,
parent.computers.filter_version,
parent.computers.model_identifier,
parent.computers.app_release_channel,
parent.computers.os_version,
parent.computers.id;
"""
)
}

// admin
Expand Down
3 changes: 2 additions & 1 deletion api/Sources/Api/PairQL/SuperAdmin/SuperAdmin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ extension SuperAdminRoute: RouteResponder {
static func respond(to route: Self, in context: Context) async throws -> Response {
guard case .authed(let token, let authedRoute) = route,
let superAdminToken = context.env.get("SUPER_ADMIN_TOKEN"),
token.uuidString.lowercased() == superAdminToken else {
token.uuidString.lowercased() == superAdminToken
else {
throw Abort(.notFound)
}

Expand Down
56 changes: 56 additions & 0 deletions api/Sources/Api/Routes/AdminTsCodegen.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import Gertie
import PairQL
import Tagged
import TypeScriptInterop
import Vapor

enum AdminTsCodegenRoute {
struct Response: Content {
var pairs: [String: String]
}

static var pairqlPairs: [any Pair.Type] {
[
AnalyticsOverview.self,
ParentOverviews.self,
]
}

@Sendable static func handler(_ request: Request) async throws -> Response {
let sharedAliases: [Config.Alias] = [
.init(NoInput.self, as: "void"),
.init(Date.self, as: "ISODateString"),
]
let config = Config(compact: true, aliasing: sharedAliases)

var pairs: [String: String] = [:]
for pairType in self.pairqlPairs {
pairs[pairType.name] = try self.ts(for: pairType, with: config)
}

return Response(pairs: pairs)
}

private static func ts<P: Pair>(
for type: P.Type,
with config: Config
) throws -> String {
let codegen = CodeGen(config: config)
let name = "\(P.self)"
var pair = try """
export namespace \(name) {
\(codegen.declaration(for: P.Input.self, as: "Input"))

\(codegen.declaration(for: P.Output.self, as: "Output"))
}
"""

// pairs that are only typealiases get compacted more
let pairLines = pair.split(separator: "\n")
if pairLines.count == 4, pairLines.allSatisfy({ $0.count < 60 }) {
pair = pairLines.joined(separator: "\n")
}

return pair
}
}