Projects STRLCPY GraphSpy Commits 98b28acf
🤬
  • ■ ■ ■ ■ ■
    GraphSpy/GraphSpy.py
    skipped 22 lines
    23 23   con.execute('CREATE TABLE devicecodes (id INTEGER PRIMARY KEY AUTOINCREMENT, generated_at INTEGER, expires_at INTEGER, user_code TEXT, device_code TEXT, interval INTEGER, client_id TEXT, status TEXT, last_poll INTEGER)')
    24 24   con.execute('CREATE TABLE request_templates (id INTEGER PRIMARY KEY AUTOINCREMENT, template_name TEXT, uri TEXT, method TEXT, request_type TEXT, body TEXT, headers TEXT, variables TEXT)')
    25 25   con.execute('CREATE TABLE settings (setting TEXT UNIQUE, value TEXT)')
    26  - # Valid Settings: active_access_token_id, active_refresh_token_id, schema_version
     26 + # Valid Settings: active_access_token_id, active_refresh_token_id, schema_version, user_agent
    27 27   cur = con.cursor()
    28 28   cur.execute("INSERT INTO settings (setting, value) VALUES ('schema_version', '2')")
    29 29   con.commit()
    skipped 53 lines
    83 83   
    84 84  # ========== Helper Functions ==========
    85 85   
     86 +def get_user_agent():
     87 + user_agent = query_db("SELECT value FROM settings where setting = 'user_agent'",one=True)
     88 + if user_agent:
     89 + return user_agent[0]
     90 + else:
     91 + return "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"
     92 + 
     93 +def set_user_agent(user_agent):
     94 + execute_db("INSERT OR REPLACE INTO settings (setting, value) VALUES ('user_agent',?)",(user_agent,))
     95 + if get_user_agent() == user_agent:
     96 + return True
     97 + else:
     98 + return False
     99 + 
    86 100  def graph_request(graph_uri, access_token_id):
    87 101   access_token = query_db("SELECT accesstoken FROM accesstokens where id = ?",[access_token_id],one=True)[0]
    88  - headers = {"Authorization":f"Bearer {access_token}"}
     102 + headers = {"Authorization":f"Bearer {access_token}", "User-Agent":get_user_agent()}
    89 103   response = requests.get(graph_uri, headers=headers)
    90 104   resp_json = response.json()
    91 105   return json.dumps(resp_json)
    92 106   
    93 107  def graph_request_post(graph_uri, access_token_id, body):
    94 108   access_token = query_db("SELECT accesstoken FROM accesstokens where id = ?",[access_token_id],one=True)[0]
    95  - headers = {"Authorization":f"Bearer {access_token}"}
     109 + headers = {"Authorization":f"Bearer {access_token}", "User-Agent":get_user_agent()}
    96 110   response = requests.post(graph_uri, headers=headers, json=body)
    97 111   resp_json = response.json()
    98 112   return json.dumps(resp_json)
    skipped 1 lines
    100 114  def generic_request(uri, access_token_id, method, request_type, body, headers):
    101 115   access_token = query_db("SELECT accesstoken FROM accesstokens where id = ?",[access_token_id],one=True)[0]
    102 116   headers["Authorization"] = f"Bearer {access_token}"
     117 + headers["User-Agent"] = get_user_agent()
    103 118   
    104 119   # Empty body
    105 120   if not body:
    skipped 73 lines
    179 194   return False
    180 195   
    181 196  def get_tenant_id(tenant_domain):
    182  - response = requests.get(f"https://login.microsoftonline.com/{tenant_domain}/.well-known/openid-configuration")
     197 + headers = {"User-Agent":get_user_agent()}
     198 + response = requests.get(f"https://login.microsoftonline.com/{tenant_domain}/.well-known/openid-configuration", headers=headers)
    183 199   resp_json = response.json()
    184 200   tenant_id = resp_json["authorization_endpoint"].split("/")[3]
    185 201   return tenant_id
    skipped 10 lines
    196 212   "scope": "openid"
    197 213   }
    198 214   url = f"https://login.microsoftonline.com/{tenant_id}/oauth2/token?api-version=1.0"
    199  - response = requests.post(url, data=body)
     215 + headers = {"User-Agent":get_user_agent()}
     216 + response = requests.post(url, data=body, headers=headers)
    200 217   access_token = response.json()["access_token"]
    201 218   save_access_token(access_token, f"Created using refresh token {refresh_token_id}")
    202 219   access_token_id = query_db("SELECT id FROM accesstokens where accesstoken = ?",[access_token],one=True)[0]
    skipped 22 lines
    225 242   "client_id": client_id
    226 243   }
    227 244   url = "https://login.microsoftonline.com/common/oauth2/devicecode?api-version=1.0"
    228  - response = requests.post(url, data=body)
     245 + headers = {"User-Agent":get_user_agent()}
     246 + response = requests.post(url, data=body,headers=headers)
    229 247   
    230 248   execute_db("INSERT INTO devicecodes (generated_at, expires_at, user_code, device_code, interval, client_id, status, last_poll) VALUES (?,?,?,?,?,?,?,?)",(
    231 249   int(datetime.now().timestamp()),
    skipped 32 lines
    264 282   "code": row["device_code"]
    265 283   }
    266 284   url = "https://login.microsoftonline.com/Common/oauth2/token?api-version=1.0"
    267  - response = requests.post(url, data=body)
     285 + headers = {"User-Agent":get_user_agent()}
     286 + response = requests.post(url, data=body, headers=headers)
    268 287   execute_db("UPDATE devicecodes SET last_poll = ? WHERE device_code = ?",(int(datetime.now().timestamp()),row["device_code"]))
    269 288   if response.status_code == 200 and "access_token" in response.json():
    270 289   access_token = response.json()["access_token"]
    skipped 440 lines
    711 730   #settings_json = [{setting["setting"] : setting["value"]} for setting in settings_raw]
    712 731   settings_json = {setting["setting"] : setting["value"] for setting in settings_raw}
    713 732   return settings_json
     733 +
     734 + @app.get("/api/get_user_agent")
     735 + def api_get_user_agent():
     736 + return get_user_agent()
     737 + 
     738 + @app.post("/api/set_user_agent")
     739 + def api_set_user_agent():
     740 + user_agent = request.form['user_agent'] if "user_agent" in request.form else ""
     741 + if not user_agent:
     742 + return "[Error] User agent not specified!", 400
     743 + if not set_user_agent(user_agent):
     744 + return f"[Error] Unable to set user agent to '{user_agent}'!", 400
     745 + return f"[Success] User agent set to '{user_agent}'!"
    714 746   
    715 747   # ========== Other ==========
    716 748   
    skipped 74 lines
  • ■ ■ ■ ■ ■ ■
    GraphSpy/static/js/functions.js
    skipped 202 lines
    203 203   $('#dt-error-message-button-enabled').toggleClass("active")
    204 204  }
    205 205   
     206 +// ========== User Agent ==========
     207 + 
     208 +function getUserAgent() {
     209 + let response = $.ajax({
     210 + type: "GET",
     211 + async: false,
     212 + url: "/api/get_user_agent"
     213 + });
     214 + if (response.status == 200) {
     215 + return response.responseText
     216 + }
     217 + return "Unable to obtain user agent."
     218 +}
     219 + 
     220 +function setUserAgent(userAgent) {
     221 + let response = $.ajax({
     222 + type: "POST",
     223 + async: false,
     224 + url: "/api/set_user_agent",
     225 + data: { "user_agent": userAgent }
     226 + });
     227 + bootstrapToast("Set User Agent", response.responseText)
     228 +}
     229 + 
    206 230  // ========== Cookies ==========
    207 231   
    208 232  function getCookie(name) {
    skipped 97 lines
  • ■ ■ ■ ■ ■ ■
    GraphSpy/templates/settings.html
    skipped 5 lines
    6 6   <div class="col-6">
    7 7   <h1>Settings</h1>
    8 8   <div class="row g-4">
    9  - <div class="dropdown col-12">
    10  - <button class="btn btn-primary dropdown-toggle" id="bd-theme" type="button" aria-expanded="false" data-bs-toggle="dropdown" data-bs-display="static" aria-label="Toggle theme (dark)">
    11  - Select theme
    12  - </button>
    13  - <ul class="dropdown-menu" aria-labelledby="bd-theme-text">
    14  - <li>
    15  - <button type="button" class="dropdown-item" data-bs-theme-value="light" aria-pressed="false">
    16  - <i class="fi fi-rr-sun"></i> Light Mode
    17  - </button>
    18  - </li>
    19  - <li>
    20  - <button type="button" class="dropdown-item active" data-bs-theme-value="dark" aria-pressed="true">
    21  - <i class="fi fi-rr-moon-stars"></i> Dark Mode
    22  - </button>
    23  - </li>
    24  - <li>
    25  - <button type="button" class="dropdown-item" data-bs-theme-value="auto" aria-pressed="false">
    26  - <i class="fi fi-rr-magic-wand"></i> Auto
    27  - </button>
    28  - </li>
    29  - </ul>
     9 + <div class="col-12">
     10 + <div class="btn-group me-3 mt-3">
     11 + <button class="btn btn-primary dropdown-toggle" id="bd-theme" type="button" aria-expanded="false" data-bs-toggle="dropdown" data-bs-display="static" aria-label="Toggle theme (dark)">
     12 + Select theme
     13 + </button>
     14 + <ul class="dropdown-menu" aria-labelledby="bd-theme-text">
     15 + <li>
     16 + <button type="button" class="dropdown-item" data-bs-theme-value="light" aria-pressed="false">
     17 + <i class="fi fi-rr-sun"></i> Light Mode
     18 + </button>
     19 + </li>
     20 + <li>
     21 + <button type="button" class="dropdown-item active" data-bs-theme-value="dark" aria-pressed="true">
     22 + <i class="fi fi-rr-moon-stars"></i> Dark Mode
     23 + </button>
     24 + </li>
     25 + <li>
     26 + <button type="button" class="dropdown-item" data-bs-theme-value="auto" aria-pressed="false">
     27 + <i class="fi fi-rr-magic-wand"></i> Auto
     28 + </button>
     29 + </li>
     30 + </ul>
     31 + </div>
     32 + <div class="btn-group me-3 mt-3">
     33 + <button class="btn btn-primary dropdown-toggle" id="dt-error-message-dropdown" type="button" data-bs-toggle="dropdown" aria-expanded="false">
     34 + DataTable Error Messages
     35 + </button>
     36 + <ul class="dropdown-menu">
     37 + <li><button class="dropdown-item" id="dt-error-message-button-enabled" type="button" onclick="setTableErorMessages('enabled')">Enabled</button></li>
     38 + <li><button class="dropdown-item" id="dt-error-message-button-disabled" type="button" onclick="setTableErorMessages('disabled')">Disabled</button></li>
     39 + </ul>
     40 + </div>
    30 41   </div>
    31  - <div class="dropdown col-12">
    32  - <button class="btn btn-primary dropdown-toggle" id="dt-error-message-dropdown" type="button" data-bs-toggle="dropdown" aria-expanded="false">
    33  - DataTable Error Messages
    34  - </button>
    35  - <ul class="dropdown-menu">
    36  - <li><button class="dropdown-item" id="dt-error-message-button-enabled" type="button" onclick="setTableErorMessages('enabled')">Enabled</button></li>
    37  - <li><button class="dropdown-item" id="dt-error-message-button-disabled" type="button" onclick="setTableErorMessages('disabled')">Disabled</button></li>
    38  - </ul>
     42 + <div class="col-12">
     43 + <div class="input-group">
     44 + <input type="text" id="user_agent_field" placeholder="User Agent" class="form-control">
     45 + <button class="btn btn-outline-primary" type="button" onclick="update_user_agent_button()">Set User Agent</button>
     46 + </div>
    39 47   </div>
    40 48   </div>
    41 49   </div>
    42  - <div class="col-auto ms-auto">
     50 + <div class="col-auto ms-auto" style="max-width: 33%;">
    43 51   <div class="card mt-3">
    44 52   <div class="card-header" style="text-align: center"><b>Persistent Settings</b></div>
    45 53   <div class="card-body">
    skipped 13 lines
    59 67   </div>
    60 68   </div>
    61 69   </div>
    62  - <div class="col-lg-9">
     70 + <div class="col-lg-8">
    63 71   <h1>Databases</h1>
    64  - <div class="col-md-6">
     72 + <div class="col-md-9">
    65 73   <div class="input-group">
    66 74   <span class="input-group-text">Database Folder</span>
    67 75   <input class="form-control" id="db_folder" type="text" value="{{ config['graph_spy_db_folder'] }}" readonly>
    skipped 13 lines
    81 89   </thead>
    82 90   </table>
    83 91   </div>
    84  - <div class="col-lg-3">
     92 + <div class="col-lg-4">
    85 93   <h1>New Database</h1>
    86 94   <form class="row g-3">
    87 95   <div>
    skipped 71 lines
    159 167   } else {
    160 168   $('#dt-error-message-button-enabled').addClass("active")
    161 169   }
     170 + 
     171 + // User Agent
     172 + // Populate the user agent field
     173 + $("#user_agent_field").val(getUserAgent());
     174 + // Update User Agent
     175 + function update_user_agent_button() {
     176 + setUserAgent($("#user_agent_field").val());
     177 + $("#user_agent_field").val(getUserAgent());
     178 + }
     179 + 
    162 180  </script>
    163 181   {%endblock content%}
    164 182   
Please wait...
Page is in error, reload to recover