-
Notifications
You must be signed in to change notification settings - Fork 47
/
validate-sa.js
139 lines (125 loc) · 4.11 KB
/
validate-sa.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#!/usr/bin/env node
const { argv } = require('yargs')
.usage('Usage: ./$0 folder-id\nfolder-id Does SA has read Pemission to the directory ID you want to detect')
.help('h')
.alias('h', 'help')
const fs = require('fs')
const path = require('path')
const prompts = require('prompts')
const { GoogleToken } = require('gtoken')
const axios = require('@viegg/axios')
const HttpsProxyAgent = require('https-proxy-agent')
const { https_proxy } = process.env
const axins = axios.create(https_proxy ? { httpsAgent: new HttpsProxyAgent(https_proxy) } : {})
const SA_FILES = fs.readdirSync(path.join(__dirname, 'sa')).filter(v => v.endsWith('.json'))
const SA_TOKENS = SA_FILES.map(filename => {
const gtoken = new GoogleToken({
keyFile: path.join(__dirname, 'sa', filename),
scope: ['https://www.googleapis.com/auth/drive']
})
return {gtoken, filename}
})
main()
async function main () {
const [fid] = argv._
if (validate_fid(fid)) {
console.log('Start testing', SA_TOKENS.length, 'SA accounts')
const invalid_sa = await get_invalid_sa(SA_TOKENS, fid)
if (!invalid_sa.length) return console.log('Detected', SA_TOKENS.length, 'Individual SA,No invalid account detected')
const choice = await choose(invalid_sa.length)
if (choice === 'yes') {
mv_sa(invalid_sa)
console.log('Successfully moved')
} else {
console.log('Successful exit, invalid SA record:', invalid_sa)
}
} else {
console.warn('Folder ID is missing or malformed')
}
}
function mv_sa (arr) {
for (const filename of arr) {
const oldpath = path.join(__dirname, 'sa', filename)
const new_path = path.join(__dirname, 'sa/invalid', filename)
fs.renameSync(oldpath, new_path)
}
}
async function choose (count) {
const answer = await prompts({
type: 'select',
name: 'value',
message: `Detcted ${count} Invalid SA,Whether to move them to the sa/invalid Folder?`,
choices: [
{ title: 'Yes', description: 'Confirm Move', value: 'yes' },
{ title: 'No', description: 'Exit without making changes', value: 'no' }
],
initial: 0
})
return answer.value
}
async function get_invalid_sa (arr, fid) {
if (!fid) throw new Error('Please specify the ID of the directory to check permissions')
const fails = []
let flag = 0
let good = 0
for (const v of arr) {
console.log('Inspection Progress', `${flag++}/${arr.length}`)
console.log('Normal/Abnormal', `${good}/${fails.length}`)
const {gtoken, filename} = v
try {
const access_token = await get_sa_token(gtoken)
await get_info(fid, access_token)
good++
} catch (e) {
handle_error(e)
const status = e && e.response && e.response.status
if (Number(status) === 400) fails.push(filename) // access_token Failed
const data = e && e.response && e.response.data
const code = data && data.error && data.error.code
if ([404, 403].includes(Number(code))) fails.push(filename) // Failed to read folder information
}
}
return fails
}
function handle_error (err) {
const data = err && err.response && err.response.data
if (data) {
console.error(JSON.stringify(data))
} else {
console.error(err.message)
}
}
async function get_info (fid, access_token) {
let url = `https://www.googleapis.com/drive/v3/files/${fid}`
let params = {
includeItemsFromAllDrives: true,
supportsAllDrives: true,
corpora: 'allDrives',
fields: 'id,name'
}
url += '?' + params_to_query(params)
const headers = { authorization: 'Bearer ' + access_token }
const { data } = await axins.get(url, { headers })
return data
}
function params_to_query (data) {
const ret = []
for (let d in data) {
ret.push(encodeURIComponent(d) + '=' + encodeURIComponent(data[d]))
}
return ret.join('&')
}
async function get_sa_token (gtoken) {
return new Promise((resolve, reject) => {
gtoken.getToken((err, tk) => {
err ? reject(err) : resolve(tk.access_token)
})
})
}
function validate_fid (fid) {
if (!fid) return false
fid = String(fid)
if (fid.length < 10 || fid.length > 100) return false
const reg = /^[a-zA-Z0-9_-]+$/
return fid.match(reg)
}