1. The left side shows a list of theme assets. Each time a user clicks an asset, its action buttons—Delete File, Rename, and Save—change according to the selected asset. See Figure 1.

2. For example, for ajax-loader.gif, only the actions Delete File and Rename are allowed; the action Save is not allowed. See Figure 2.

3. For example, for settings_data.json, only the action Save is allowed; the actions Delete File and Rename are not allowed. See Figure 3.

4. I checked the network request for the file page on GitHub. Viewing README.md at the request URL: https://github.com/shuijingwan/larabbs/blob/main/README.md, the response is in HTML structure, but it allows the actions Edit File and Delete File. See Figure 4.

5. I checked the REST API for fetching a file on GitHub. Viewing README.md at the request URL: /repos/{owner}/{repo}/readme, the response is in JSON structure, but it lacks a field indicating whether an action is allowed. See Figure 5.

6. I checked the GitHub App permissions. Searching for /repos/:owner/:repo/readme, it only indicates that this endpoint is of the read type. It does not define more specific action permissions based on the specific current user and the specific file. This is a granular permission within the endpoint itself. See Figure 6.

7. I checked the GraphQL API for fetching a file on GitHub. Requesting resource returns the type: UniformResourceLocatable. See Figure 7.

8. Looking at the type: UniformResourceLocatable, it is essentially an interface type. Looking at another interface type: Updatable, the permission control for theme asset actions should be implemented with reference to Updatable. It checks whether the current user can update this object. See Figure 8.

9. Referring to the Explorer usage, I plan to make the request in Altair. I opened a new window: https://api.github.com/graphql, and clicked Set Headers in the upper left corner. See Figure 9.

10. In the Key field, enter Authorization. In the Value field, enter Bearer <token>, where <token> is the OAuth token you generated. See Figure 10.

11. Test your access with a self-query; the test passed. See Figure 11.

Request
query {
viewer {
login
}
}
Response
{
"data": {
"viewer": {
"login": "shuijingwan"
}
}
}
12. Querying the resource: https://github.com/shuijingwan/larabbs/blob/main/README.md returns a null response, with no response field indicating whether the update action is allowed. See Figure 12.

13. Querying the project with ID 1 under a user, I fetched the single project and the project list respectively, along with viewerCanUpdate. See Figure 13.

Request
query{
user(login: "shuijingwan"){
project(number: 1){
viewerCanUpdate
}
...projects
}
}
fragment projects on User{
projects(first:1){
edges{
cursor
node{
viewerCanUpdate
}
}
totalCount
}
}
Response
{
"data": {
"user": {
"project": {
"viewerCanUpdate": true
},
"projects": {
"edges": [
{
"cursor": "Y3Vyc29yOnYyOpHOANZ4WQ==",
"node": {
"viewerCanUpdate": true
}
}
],
"totalCount": 1
}
}
}
}
14. I ultimately decided to implement the type themeAsset(key:String!) and add the following fields to the response: deletable, renameable, and updatable. See Figure 14.

Request
query{
onlineStoreTheme(themeId: "vogue"){
...themeAsset
}
}
fragment themeAsset on OnlineStoreTheme {
themeAsset(key: "assets/iconfont/iconfont.css") {
id
themeId
version
content
key
mimeType
category
schema
createdAt
updatedAt
deletable
renameable
updatable
}
}
Response
{
"data": {
"onlineStoreTheme": {
"themeAsset": {
"id": "1",
"themeId": "vogue",
"version": "",
"content": "@font-face {\n font-family: \"iconfont\"; /* Project id 2455235 */\n src: \n url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2');\n}\n\n.iconfont {\n font-family: \"iconfont\" !important;\n font-size: 16px;\n font-style: normal;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n.icon-shouqidefuben:before {\n content: \"\\e61f\";\n}\n\n.icon-zhankai:before {\n content: \"\\e620\";\n}\n\n.icon-guanbiicon:before {\n content: \"\\e605\";\n}\n\n.icon-yigou:before {\n content: \"\\e606\";\n}\n\n.icon-bofang:before {\n content: \"\\e940\";\n}\n\n.icon-fanyeyou:before {\n content: \"\\e61d\";\n}\n\n.icon-you1:before {\n content: \"\\e7b9\";\n}\n\n.icon-fanyezuo:before {\n content: \"\\e61c\";\n}\n\n.icon-diqiu:before {\n content: \"\\e844\";\n}\n\n.icon-youtube:before {\n content: \"\\e612\";\n}\n\n.icon-instagram:before {\n content: \"\\f1d3\";\n}\n\n.icon-leftarrow:before {\n content: \"\\e691\";\n}\n\n.icon-sousuo:before {\n content: \"\\e6b9\";\n}\n\n.icon-youjiantou1:before {\n content: \"\\e609\";\n}\n\n.icon-sanjiaodown:before {\n content: \"\\e6b5\";\n}\n\n.icon-huobi:before {\n content: \"\\e608\";\n}\n\n.icon-earth:before {\n content: \"\\e9ee\";\n}\n\n.icon-menu:before {\n content: \"\\e633\";\n}\n\n.icon-LC_icon_search_line_2:before {\n content: \"\\e60e\";\n}\n\n.icon-gouwuche:before {\n content: \"\\e61b\";\n}\n\n.icon-ren:before {\n content: \"\\e6c5\";\n}\n\n.icon-youjiantoufuben:before {\n content: \"\\e64d\";\n}\n\n.icon-bofang1:before {\n content: \"\\e6c6\";\n}\n\n.icon-you:before {\n content: \"\\e671\";\n}\n\n.icon-zuo:before {\n content: \"\\e6f7\";\n}\n\n.icon-xia:before {\n content: \"\\e63c\";\n}\n\n.icon-youjiantou2:before {\n content: \"\\e602\";\n}\n\n.icon-zuojiantou:before {\n content: \"\\e603\";\n}\n\n.icon-jingdiananli_wujiaoxing_shoucanghou:before {\n content: \"\\e64a\";\n}\n\n.icon-jingdiananli_kongwujiaoxing_shoucang:before {\n content: \"\\e64b\";\n}\n\n.icon-icontouxiang:before {\n content: \"\\e678\";\n}\n\n.icon-gou:before {\n content: \"\\e63b\";\n}\n\n.icon-web__bitebiyoujiantou:before {\n content: \"\\e62f\";\n}\n\n.icon-web__bitebizuojiantou:before {\n content: \"\\e630\";\n}\n\n.icon-cancel-1-copy:before {\n content: \"\\e61a\";\n}\n\n.icon-shangxia:before {\n content: \"\\e60b\";\n}\n\n.icon-gouwucheman:before {\n content: \"\\e604\";\n}\n\n.icon-duigou:before {\n content: \"\\e60f\";\n}\n\n.icon-xiajiantou1:before {\n content: \"\\e62a\";\n}\n\n.icon-_pinterest:before {\n content: \"\\e653\";\n}\n\n.icon-icomoonfacebook:before {\n content: \"\\e654\";\n}\n\n.icon-guge1:before {\n content: \"\\e655\";\n}\n\n.icon-twitter:before {\n content: \"\\e656\";\n}\n\n.icon-biaoqian:before {\n content: \"\\e718\";\n}\n\n.icon-2:before {\n content: \"\\e601\";\n}\n\n",
"key": "assets/iconfont/iconfont.css",
"mimeType": "text/plain",
"category": "unknown",
"schema": null,
"createdAt": "2022-02-15 09:59:41",
"updatedAt": "2022-02-15 09:59:41",
"deletable": false,
"renameable": false,
"updatable": false
}
}
}
}
