Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🐛 Fix min record takedown filter and add stats on repositories page #281

Merged
merged 2 commits into from
Jan 24, 2025
Merged
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
1 change: 1 addition & 0 deletions app/reports/page-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ function useModerationQueueQuery() {
collections,
minAccountSuspendCount,
minReportedRecordsCount,
minTakendownRecordsCount,
},
],
queryFn: async ({ pageParam }) => {
Expand Down
1 change: 0 additions & 1 deletion components/reports/useQueueFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@ export const useQueueFilter = () => {

return {
queueFilters,
updateFilters,
updateTagExclusions,
addTags,
toggleCollection,
Expand Down
52 changes: 25 additions & 27 deletions components/repositories/AccountView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ import { DidHistory } from './DidHistory'
import { InviteCodeGenerationStatus } from './InviteCodeGenerationStatus'
import { MuteReporting } from './MuteReporting'
import { ProfileAvatar } from './ProfileAvatar'
import { obscureIp, parseThreatSigs } from './helpers'

enum Views {
Details,
Expand Down Expand Up @@ -528,8 +529,14 @@ function Details({
? dateFormatter.format(new Date(repo.deactivatedAt))
: ''

const { registrationIp, lastSigninIp, lastSigninTime, hcapDetail } =
parseThreatSigs(repo.threatSignatures)
const {
registrationIp,
lastSigninIp,
lastSigninTime,
hcapDetail,
ipCountry,
lastSigninCountry,
} = parseThreatSigs(repo.threatSignatures)

return (
<div className="mx-auto mt-6 max-w-5xl px-4 sm:px-6 lg:px-8">
Expand Down Expand Up @@ -557,6 +564,13 @@ function Details({
>
<MagnifyingGlassIcon className="h-3 w-3 inline" />
</Link>
{ipCountry && (
<Link
href={`/repositories?term=sig:${encodeURIComponent(ipCountry)}`}
>
<LabelChip>{ipCountry}</LabelChip>
</Link>
)}
</DataField>
)}
{lastSigninIp && (
Expand All @@ -569,6 +583,15 @@ function Details({
>
<MagnifyingGlassIcon className="h-3 w-3 inline" />
</Link>
{lastSigninCountry && (
<Link
href={`/repositories?term=sig:${encodeURIComponent(
lastSigninCountry,
)}`}
>
<LabelChip>{lastSigninCountry}</LabelChip>
</Link>
)}
{lastSigninTime && (
<div className="text-gray-400">
{new Date(lastSigninTime).toLocaleString()}
Expand Down Expand Up @@ -932,28 +955,3 @@ const EmailView = (props: ComponentProps<typeof EmailComposer>) => {
</div>
)
}

function obscureIp(ip: string) {
const parts = ip.split('.')
if (parts.length !== 4) return '***.***.***.***'
return `${parts[0]}.${parts[1]}.***.***`
}

function parseThreatSigs(sigs?: ComAtprotoAdminDefs.ThreatSignature[]) {
const registrationIp = sigs?.find(
(sig) => sig.property === 'registrationIp',
)?.value
const lastSigninIp = sigs?.find(
(sig) => sig.property === 'lastSigninIp',
)?.value
const lastSigninTime = sigs?.find(
(sig) => sig.property === 'lastSigninTime',
)?.value
const hcapDetail = sigs?.filter(
(sig) =>
!['registrationIp', 'lastSigninIp', 'lastSigninTime'].includes(
sig.property,
),
)
return { registrationIp, lastSigninIp, lastSigninTime, hcapDetail }
}
61 changes: 58 additions & 3 deletions components/repositories/RepositoriesTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ import { LoadMoreButton } from '../common/LoadMoreButton'
import { ReviewStateIcon } from '@/subject/ReviewStateMarker'
import { SubjectOverview } from '@/reports/SubjectOverview'
import { Loading } from '@/common/Loader'
import { obscureIp, parseThreatSigs } from './helpers'
import Link from 'next/link'
import { MagnifyingGlassIcon } from '@heroicons/react/24/solid'
import { LabelChip } from '@/common/labels'
import { SubjectSummaryColumn } from '@/subject/table'

export function RepositoriesTable(props: {
repos: Repo[]
Expand Down Expand Up @@ -71,6 +76,9 @@ function RepoRow(props: { repo: Repo; showEmail: boolean }) {
const { repo, showEmail, ...others } = props
const profile = repo.relatedRecords.find(AppBskyActorProfile.isRecord)
const displayName = profile?.displayName

const { registrationIp, lastSigninIp, ipCountry, lastSigninCountry } =
parseThreatSigs(repo.threatSignatures)
const indexedAt = new Date(repo.indexedAt)
const { subjectStatus } = repo.moderation
return (
Expand All @@ -89,6 +97,29 @@ function RepoRow(props: { repo: Repo; showEmail: boolean }) {
/>
)}
</div>
{lastSigninCountry && (
<div>
Last:
<Link
prefetch={false}
href={`/repositories?term=sig:${encodeURIComponent(
lastSigninIp,
)}`}
>
{obscureIp(lastSigninIp)}{' '}
<MagnifyingGlassIcon className="h-3 w-3 inline" />
</Link>
{lastSigninCountry && (
<Link
href={`/repositories?term=sig:${encodeURIComponent(
lastSigninCountry,
)}`}
>
<LabelChip>{lastSigninCountry}</LabelChip>
</Link>
)}
</div>
)}
{subjectStatus?.comment && (
<p className="text-xs dark:text-gray-300 text-gray-700 max-w-xs">
<b>Note:</b> {subjectStatus.comment}
Expand All @@ -99,7 +130,6 @@ function RepoRow(props: { repo: Repo; showEmail: boolean }) {
<dd className="mt-1 truncate text-gray-700 dark:text-gray-100">
{displayName}
</dd>
<dt className="sr-only sm:hidden">Type</dt>
</dl>
</td>
{showEmail && (
Expand All @@ -108,12 +138,37 @@ function RepoRow(props: { repo: Repo; showEmail: boolean }) {
</td>
)}
<td className="hidden px-3 py-4 text-sm text-gray-500 dark:text-gray-50 lg:table-cell">
{displayName}
{displayName}{' '}
{registrationIp && (
<div>
Reg:
<Link
prefetch={false}
href={`/repositories?term=sig:${encodeURIComponent(
registrationIp,
)}`}
>
{obscureIp(registrationIp)}{' '}
<MagnifyingGlassIcon className="h-3 w-3 inline" />
</Link>
{ipCountry && (
<Link
href={`/repositories?term=sig:${encodeURIComponent(ipCountry)}`}
>
<LabelChip>{ipCountry}</LabelChip>
</Link>
)}
</div>
)}
</td>
<td className="hidden px-3 py-4 text-sm text-gray-500 dark:text-gray-50 lg:table-cell">
<span title={indexedAt.toLocaleString()}>
{formatDistanceToNow(indexedAt, { addSuffix: true })}
</span>
<SubjectSummaryColumn
accountStats={subjectStatus?.accountStats}
recordStats={subjectStatus?.recordsStats}
/>
</td>
</tr>
)
Expand All @@ -140,7 +195,7 @@ function RepoRowHead({ showEmail = false }) {
scope="col"
className="hidden px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-200 lg:table-cell"
>
Name
Name/Details
</th>
<th
scope="col"
Expand Down
49 changes: 49 additions & 0 deletions components/repositories/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { ComAtprotoAdminDefs } from '@atproto/api'

export function obscureIp(ip: string) {
const parts = ip.split('.')
if (parts.length !== 4) return '***.***.***.***'
return `${parts[0]}.${parts[1]}.***.***`
}

export function parseThreatSigs(sigs?: ComAtprotoAdminDefs.ThreatSignature[]) {
const hcapDetail: ComAtprotoAdminDefs.ThreatSignature[] = []
let registrationIp,
lastSigninIp,
lastSigninTime,
lastSigninCountry,
ipCountry: string | undefined

if (sigs) {
for (const sig of sigs) {
switch (sig.property) {
case 'registrationIp':
registrationIp = sig.value
break
case 'lastSigninIp':
lastSigninIp = sig.value
break
case 'lastSigninTime':
lastSigninTime = sig.value
break
case 'lastSigninCountry':
lastSigninCountry = sig.value
break
case 'ipCountry':
ipCountry = sig.value
break
default:
hcapDetail.push(sig)
}
}
}

return {
registrationIp,
lastSigninIp,
lastSigninTime,
lastSigninCountry,
ipCountry,
hcapDetail,
}
}
2 changes: 1 addition & 1 deletion components/subject/table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export function SubjectTable(
)
}

const SubjectSummaryColumn = ({
export const SubjectSummaryColumn = ({
recordStats,
accountStats,
}: {
Expand Down
Loading