microslop_one_drive 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.txt +1 -0
- data/README.md +160 -0
- data/lib/microslop_one_drive/audience.rb +32 -0
- data/lib/microslop_one_drive/client.rb +113 -0
- data/lib/microslop_one_drive/drive.rb +14 -0
- data/lib/microslop_one_drive/drive_item.rb +99 -0
- data/lib/microslop_one_drive/drive_item_list.rb +32 -0
- data/lib/microslop_one_drive/drive_list.rb +13 -0
- data/lib/microslop_one_drive/errors/client_error.rb +13 -0
- data/lib/microslop_one_drive/list_response.rb +19 -0
- data/lib/microslop_one_drive/permission.rb +11 -0
- data/lib/microslop_one_drive/permission_batch.rb +60 -0
- data/lib/microslop_one_drive/permission_list.rb +25 -0
- data/lib/microslop_one_drive/user.rb +12 -0
- data/lib/microslop_one_drive/utils.rb +11 -0
- data/lib/microslop_one_drive/version.rb +3 -0
- data/lib/microslop_one_drive.rb +17 -0
- metadata +131 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: bf99630f0f09cb4d635d7881c2db5b0d53af498f33b32724b1522d10cd464985
|
|
4
|
+
data.tar.gz: a5111efbd38ae81fe7d06524461bade0fe49761a82dccad1747f09c8ae0c751b
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 2d683dcebe786a18941e751f0e8f9fa5962d266e9eb69e1ceadcafa1c710a563de06b3ee7153ef4cf0350658c0b735bb55e1ea45a5f6071212c66339696514c5
|
|
7
|
+
data.tar.gz: a2141155fc90fdc9c07bb7b725ee43d130d0e8e4e320193840a013621b0c1d0b6b901d5cd1d9df72e2635aab33514760473a39ab246630c52654ee56a5f82c97
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Proprietary for now
|
data/README.md
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# MicroslopOneDrive
|
|
2
|
+
|
|
3
|
+
Microslop OneDrive API client.
|
|
4
|
+
|
|
5
|
+
See <https://learn.microsoft.com/en-us/onedrive/developer/rest-api/>
|
|
6
|
+
|
|
7
|
+
Graph explorer (API sandbox): <https://developer.microsoft.com/en-us/graph/graph-explorer>
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```rb
|
|
12
|
+
TODO: DOCUMENT
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
### Create a client
|
|
18
|
+
|
|
19
|
+
```rb
|
|
20
|
+
access_token = "..." # Get an access token via OAuth 2.0
|
|
21
|
+
|
|
22
|
+
client = MicroslopOneDrive::Client.new(access_token)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Get the current user
|
|
26
|
+
|
|
27
|
+
```rb
|
|
28
|
+
me = client.me
|
|
29
|
+
me.class # => MicroslopOneDrive::User
|
|
30
|
+
me.email_address # => person@example.com
|
|
31
|
+
me.display_name # => Example Person
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Get a list of the user's Drives
|
|
35
|
+
|
|
36
|
+
```rb
|
|
37
|
+
drive_list = client.drives
|
|
38
|
+
|
|
39
|
+
drive_list.class # => MicroslopOneDrive::DriveList
|
|
40
|
+
drive_list.next_page? # => false
|
|
41
|
+
drive_list.drives # => [MicroslopOneDrive::Drive, ...]
|
|
42
|
+
|
|
43
|
+
drive = drive_list.drives.first
|
|
44
|
+
drive.class # => MicroslopOneDrive::Drive
|
|
45
|
+
drive.id # => "0f0**********42"
|
|
46
|
+
drive.name # => "OneDrive"
|
|
47
|
+
drive.url # => "https://my.microsoftpersonalcontent.com/..."
|
|
48
|
+
drive.drive_type # => "personal"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Get a single Drive
|
|
52
|
+
|
|
53
|
+
```rb
|
|
54
|
+
drive = client.drive(drive_id: "0f097********a42")
|
|
55
|
+
|
|
56
|
+
drive.class # => MicroslopOneDrive::Drive
|
|
57
|
+
drive.id # => "0f097********a42"
|
|
58
|
+
drive.name # => "OneDrive"
|
|
59
|
+
drive.url # => "https://my.microsoftpersonalcontent.com/personal/..."
|
|
60
|
+
drive.drive_type # => "personal"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Get a delta of changes to a Drive
|
|
64
|
+
|
|
65
|
+
```rb
|
|
66
|
+
# Initial delta (all current items + token for later)
|
|
67
|
+
drive_item_list = client.delta(drive_id: "0f097********a42")
|
|
68
|
+
|
|
69
|
+
drive_item_list.class # => MicroslopOneDrive::DriveItemList
|
|
70
|
+
drive_item_list.items # => [MicroslopOneDrive::DriveItem, ...]
|
|
71
|
+
|
|
72
|
+
drive_item_list.next_page? # => true if more pages
|
|
73
|
+
drive_item_list.next_token # => use with delta(drive_id:, token:) for next page
|
|
74
|
+
drive_item_list.delta_link # => URL for incremental sync (when no next_page?)
|
|
75
|
+
drive_item_list.delta_token # => use with delta(drive_id:, token:) for incremental sync
|
|
76
|
+
|
|
77
|
+
# Next page (if next_page? was true)
|
|
78
|
+
client.delta(drive_id: "0f097********a42", token: drive_item_list.next_token)
|
|
79
|
+
|
|
80
|
+
# Incremental sync (only changes since last delta)
|
|
81
|
+
client.delta(drive_id: "0f097********a42", token: saved_delta_token)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Delta items have parent/child set: `item.parent`, `item.children`, and `item.path` (e.g. `"root:/folder/subfolder/file.txt"`).
|
|
85
|
+
|
|
86
|
+
### Get a DriveItem (file or folder)
|
|
87
|
+
|
|
88
|
+
```rb
|
|
89
|
+
item = client.drive_item(item_id: "F0**********42!sa466********************1479272d27")
|
|
90
|
+
|
|
91
|
+
item.class # => MicroslopOneDrive::DriveItem
|
|
92
|
+
item.name # => "Getting started with OneDrive.pdf"
|
|
93
|
+
item.identifier # => "F0**********42!sa466********************1479272d27"
|
|
94
|
+
item.url # => "https://onedrive.live.com?cid=..."
|
|
95
|
+
item.file? # => true
|
|
96
|
+
item.folder? # => false
|
|
97
|
+
item.mime_type # => "application/pdf"
|
|
98
|
+
item.size # => 1053417
|
|
99
|
+
item.created_at # => 2026-02-19 07:35:52 UTC
|
|
100
|
+
item.updated_at # => 2026-02-19 07:35:52 UTC
|
|
101
|
+
item.parent_identifier # => "F0**********42!sea8cc6b********************5c639"
|
|
102
|
+
item.deleted? # => false
|
|
103
|
+
item.shared? # => true if the item has sharing info
|
|
104
|
+
item.path # => "root:/Documents/Getting started with OneDrive.pdf" (from delta only; nil for single item)
|
|
105
|
+
item.is_root? # => true for root folder
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Check if a DriveItem exists
|
|
109
|
+
|
|
110
|
+
```rb
|
|
111
|
+
client.item_exists?(item_id: "F0**********42!sa466********************1479272d27") # => true
|
|
112
|
+
client.item_exists?(item_id: "F0**********42!not-an-item-id") # => false
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Get permissions for a DriveItem
|
|
116
|
+
|
|
117
|
+
```rb
|
|
118
|
+
permission_list = client.permissions(item_id: "F0**********42!sa466********************1479272d27")
|
|
119
|
+
permission_list.class # => MicroslopOneDrive::PermissionList
|
|
120
|
+
permission_list.permissions # => [MicroslopOneDrive::Permission, ...]
|
|
121
|
+
|
|
122
|
+
permission = permission_list.permissions.first
|
|
123
|
+
permission.role # => "write" or "owner" etc.
|
|
124
|
+
permission.audience.type # => "user" or "anyone"
|
|
125
|
+
permission.audience.identifier # => email for user, "anyone_with_the_link" for link
|
|
126
|
+
permission.audience.display_name # => "Amy Smith"
|
|
127
|
+
permission.audience.email_address # => "amy@example.com" (nil for "anyone with the link")
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Returns an empty permission list if the item does not exist (404).
|
|
131
|
+
|
|
132
|
+
## Contributing
|
|
133
|
+
|
|
134
|
+
### Setup
|
|
135
|
+
|
|
136
|
+
```sh
|
|
137
|
+
mise init
|
|
138
|
+
bundle install
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Running tests
|
|
142
|
+
|
|
143
|
+
```sh
|
|
144
|
+
bundle exec rake test
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Building and publishing
|
|
148
|
+
|
|
149
|
+
```sh
|
|
150
|
+
# Signin if not already:
|
|
151
|
+
gem signin
|
|
152
|
+
|
|
153
|
+
# Bump version in lib/microslop_one_drive/version.rb
|
|
154
|
+
|
|
155
|
+
# Then build:
|
|
156
|
+
gem build microslop_drive.gemspec
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
gem push microslop_one_drive-0.1.0.gem
|
|
160
|
+
```
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module MicroslopOneDrive
|
|
2
|
+
class Audience
|
|
3
|
+
attr_reader :type, :identifier, :display_name, :email_address
|
|
4
|
+
|
|
5
|
+
def initialize(type:, identifier:, display_name:, email_address: nil)
|
|
6
|
+
@type = type
|
|
7
|
+
@identifier = identifier
|
|
8
|
+
@display_name = display_name
|
|
9
|
+
@email_address = email_address
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Converts a "siteUser" object into an OneDriveAudience object.
|
|
13
|
+
#
|
|
14
|
+
# A siteUser object looks like this:
|
|
15
|
+
#
|
|
16
|
+
# {
|
|
17
|
+
# "displayName" => "Bob Bentley",
|
|
18
|
+
# "email" => "bob@haikucode.dev",
|
|
19
|
+
# "id" => "12",
|
|
20
|
+
# "loginName" => "i:0#.f|membership|bob@haikucode.dev"
|
|
21
|
+
# }
|
|
22
|
+
#
|
|
23
|
+
def self.from_site_user(site_user)
|
|
24
|
+
new(
|
|
25
|
+
type: "user",
|
|
26
|
+
identifier: site_user.fetch("email"),
|
|
27
|
+
display_name: site_user.fetch("displayName"),
|
|
28
|
+
email_address: site_user.fetch("email")
|
|
29
|
+
)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
module MicroslopOneDrive
|
|
2
|
+
class Client
|
|
3
|
+
BASE_URL = "https://graph.microsoft.com/v1.0".freeze
|
|
4
|
+
|
|
5
|
+
def initialize(access_token)
|
|
6
|
+
@access_token = access_token
|
|
7
|
+
|
|
8
|
+
@headers = {
|
|
9
|
+
"Authorization" => "Bearer #{@access_token}",
|
|
10
|
+
"Content-Type" => "application/json",
|
|
11
|
+
"Prefer" => "hierarchicalsharing"
|
|
12
|
+
}
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Gets the current user
|
|
16
|
+
#
|
|
17
|
+
# @return [MicroslopOneDrive::User]
|
|
18
|
+
def me
|
|
19
|
+
response = get(path: "me", query: {})
|
|
20
|
+
handle_error(response) unless response.success?
|
|
21
|
+
MicroslopOneDrive::User.new(response.parsed_response)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Gets all Drives the current user has access to.
|
|
25
|
+
#
|
|
26
|
+
# NOTE: This will include some internal Microsoft drives that aren't real drives, such as AI, Face scans, and other
|
|
27
|
+
# shitty things.
|
|
28
|
+
#
|
|
29
|
+
# @return [MicroslopOneDrive::DriveList]
|
|
30
|
+
def drives
|
|
31
|
+
response = get(path: "me/drives", query: {})
|
|
32
|
+
handle_error(response) unless response.success?
|
|
33
|
+
MicroslopOneDrive::DriveList.new(response.parsed_response)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Gets a specific Drive by its ID.
|
|
37
|
+
#
|
|
38
|
+
# @param drive_id [String] The ID of the Drive to get.
|
|
39
|
+
#
|
|
40
|
+
# @return [MicroslopOneDrive::Drive]
|
|
41
|
+
def drive(drive_id:)
|
|
42
|
+
response = get(path: "me/drives/#{drive_id}", query: {})
|
|
43
|
+
handle_error(response) unless response.success?
|
|
44
|
+
MicroslopOneDrive::Drive.new(response.parsed_response)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Gets a specific DriveItem (folder or file) by its ID.
|
|
48
|
+
#
|
|
49
|
+
# @param item_id [String] The ID of the Drive Item to get.
|
|
50
|
+
#
|
|
51
|
+
# @return [MicroslopOneDrive::DriveItem]
|
|
52
|
+
def drive_item(item_id:)
|
|
53
|
+
response = get(path: "me/drive/items/#{item_id}", query: {})
|
|
54
|
+
handle_error(response) unless response.success?
|
|
55
|
+
MicroslopOneDrive::DriveItem.new(response.parsed_response)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Asks if a DriveItem (folder or file) exists by its ID.
|
|
59
|
+
#
|
|
60
|
+
# @param item_id [String] The ID of the Drive Item to check.
|
|
61
|
+
#
|
|
62
|
+
# @return [Boolean]
|
|
63
|
+
def item_exists?(item_id:)
|
|
64
|
+
response = get(path: "me/drive/items/#{item_id}", query: {})
|
|
65
|
+
|
|
66
|
+
return false if response.code == 404
|
|
67
|
+
return true if response.success?
|
|
68
|
+
|
|
69
|
+
handle_error(response)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Gets a delta of changes to a Drive.
|
|
73
|
+
#
|
|
74
|
+
# @param drive_id [String] The ID of the Drive to get the delta of.
|
|
75
|
+
# @param token [String] The token to use for the delta. If not provided, the initial delta will be returned.
|
|
76
|
+
#
|
|
77
|
+
# @return [MicroslopOneDrive::DriveItemList]
|
|
78
|
+
def delta(drive_id:, token: nil)
|
|
79
|
+
response = get(path: "me/drives/#{drive_id}/root/delta", query: {token: token})
|
|
80
|
+
handle_error(response) unless response.success?
|
|
81
|
+
MicroslopOneDrive::DriveItemList.new(response.parsed_response)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Gets the permissions for a DriveItem (folder or file).
|
|
85
|
+
#
|
|
86
|
+
# @param item_id [String] The ID of the Drive Item to get the permissions of.
|
|
87
|
+
#
|
|
88
|
+
# @return [MicroslopOneDrive::PermissionList]
|
|
89
|
+
def permissions(item_id:)
|
|
90
|
+
response = get(path: "me/drive/items/#{item_id}/permissions", query: {})
|
|
91
|
+
|
|
92
|
+
return MicroslopOneDrive::PermissionList.new("value" => []) if response.code == 404
|
|
93
|
+
|
|
94
|
+
handle_error(response) unless response.success?
|
|
95
|
+
MicroslopOneDrive::PermissionList.new(response.parsed_response)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
private
|
|
99
|
+
|
|
100
|
+
def get(path:, query: {})
|
|
101
|
+
response = HTTParty.get("#{BASE_URL}/#{path}", headers: @headers, query: query)
|
|
102
|
+
|
|
103
|
+
@debug_response_writer&.call(path, response.parsed_response)
|
|
104
|
+
|
|
105
|
+
response
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def handle_error(response)
|
|
109
|
+
error = MicroslopOneDrive::Errors::ClientError.new(response.parsed_response, response.code)
|
|
110
|
+
raise error
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module MicroslopOneDrive
|
|
2
|
+
class Drive
|
|
3
|
+
attr_reader :id, :name, :url, :drive_type
|
|
4
|
+
|
|
5
|
+
def initialize(drive_hash)
|
|
6
|
+
@drive_hash = drive_hash
|
|
7
|
+
|
|
8
|
+
@id = drive_hash.fetch("id", nil)
|
|
9
|
+
@name = drive_hash.fetch("name", nil)
|
|
10
|
+
@url = drive_hash.fetch("webUrl", nil)
|
|
11
|
+
@drive_type = drive_hash.fetch("driveType", nil)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
module MicroslopOneDrive
|
|
2
|
+
class DriveItem
|
|
3
|
+
DIRECTORY_MIME_TYPE = "inode/directory".freeze
|
|
4
|
+
|
|
5
|
+
attr_reader :identifier,
|
|
6
|
+
:name,
|
|
7
|
+
:created_at,
|
|
8
|
+
:updated_at,
|
|
9
|
+
:url,
|
|
10
|
+
:size,
|
|
11
|
+
:file_or_folder,
|
|
12
|
+
:parent_identifier,
|
|
13
|
+
:mime_type,
|
|
14
|
+
:parent,
|
|
15
|
+
:children,
|
|
16
|
+
:path,
|
|
17
|
+
:full_path
|
|
18
|
+
|
|
19
|
+
def initialize(item_hash)
|
|
20
|
+
@item_hash = item_hash
|
|
21
|
+
|
|
22
|
+
@identifier = @item_hash.fetch("id", nil)
|
|
23
|
+
@name = @item_hash.fetch("name", nil)
|
|
24
|
+
@url = @item_hash.fetch("webUrl", nil)
|
|
25
|
+
@size = @item_hash.fetch("size", nil)
|
|
26
|
+
|
|
27
|
+
@created_at = Utils.safe_parse_time(@item_hash.fetch("createdDateTime", nil))
|
|
28
|
+
@updated_at = Utils.safe_parse_time(@item_hash.fetch("lastModifiedDateTime", nil))
|
|
29
|
+
|
|
30
|
+
if @item_hash.key?("file")
|
|
31
|
+
@file_or_folder = :file
|
|
32
|
+
@mime_type = @item_hash.dig("file", "mimeType")
|
|
33
|
+
elsif @item_hash.key?("folder")
|
|
34
|
+
@file_or_folder = :folder
|
|
35
|
+
@mime_type = DIRECTORY_MIME_TYPE
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
@parent_identifier = @item_hash.dig("parentReference", "id")
|
|
39
|
+
|
|
40
|
+
@deleted = @item_hash.dig("deleted", "state") == "deleted"
|
|
41
|
+
|
|
42
|
+
@path = build_path
|
|
43
|
+
|
|
44
|
+
@parent = nil
|
|
45
|
+
@children = []
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def deleted?
|
|
49
|
+
@deleted
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def shared?
|
|
53
|
+
@item_hash.key?("shared")
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def file?
|
|
57
|
+
@file_or_folder == :file
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def folder?
|
|
61
|
+
@file_or_folder == :folder
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def set_parent(parent)
|
|
65
|
+
if @parent
|
|
66
|
+
@parent.remove_child(self)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
@parent = parent
|
|
70
|
+
@parent.add_child(self)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def is_root?
|
|
74
|
+
@item_hash.key?("root")
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
protected
|
|
78
|
+
|
|
79
|
+
def add_child(child)
|
|
80
|
+
@children << child
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def remove_child(child)
|
|
84
|
+
@children.delete(child)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
private
|
|
88
|
+
|
|
89
|
+
def build_path
|
|
90
|
+
return "root:" if is_root?
|
|
91
|
+
|
|
92
|
+
full_parent_path = @item_hash.dig("parentReference", "path")
|
|
93
|
+
return nil if full_parent_path.nil?
|
|
94
|
+
|
|
95
|
+
full_path_with_name = File.join(full_parent_path, @name)
|
|
96
|
+
full_path_with_name.sub(/\A.*root:\//, "root:/")
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module MicroslopOneDrive
|
|
2
|
+
class DriveItemList < ListResponse
|
|
3
|
+
attr_reader :items
|
|
4
|
+
|
|
5
|
+
def initialize(parsed_response)
|
|
6
|
+
super(parsed_response)
|
|
7
|
+
|
|
8
|
+
@parsed_response = parsed_response
|
|
9
|
+
@items = build_items
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def build_items
|
|
15
|
+
items = @parsed_response.fetch("value", []).map do
|
|
16
|
+
MicroslopOneDrive::DriveItem.new(it)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
set_parent_and_child_relationships(items)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def set_parent_and_child_relationships(items)
|
|
23
|
+
items.each do |item|
|
|
24
|
+
next if item.parent_identifier.nil?
|
|
25
|
+
parent = items.find { it.identifier == item.parent_identifier }
|
|
26
|
+
next if parent.nil?
|
|
27
|
+
|
|
28
|
+
item.set_parent(parent)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module MicroslopOneDrive
|
|
2
|
+
module Errors
|
|
3
|
+
class ClientError < StandardError
|
|
4
|
+
attr_reader :response_body, :response_code
|
|
5
|
+
|
|
6
|
+
def initialize(response_body, response_code)
|
|
7
|
+
super(response_body)
|
|
8
|
+
@response_body = response_body
|
|
9
|
+
@response_code = response_code
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module MicroslopOneDrive
|
|
2
|
+
class ListResponse
|
|
3
|
+
attr_reader :next_link, :next_token, :delta_link, :delta_token
|
|
4
|
+
|
|
5
|
+
def initialize(response_hash)
|
|
6
|
+
@response_hash = response_hash
|
|
7
|
+
|
|
8
|
+
@next_link = response_hash.fetch("@odata.nextLink", nil)
|
|
9
|
+
@next_token = @next_link.split("?token=").last if @next_link && !@next_link.empty?
|
|
10
|
+
|
|
11
|
+
@delta_link = response_hash.fetch("@odata.deltaLink", nil)
|
|
12
|
+
@delta_token = @delta_link.split("?token=").last if @delta_link && !@delta_link.empty?
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def next_page?
|
|
16
|
+
!next_link.nil?
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
module MicroslopOneDrive
|
|
2
|
+
class PermissionBatch
|
|
3
|
+
attr_reader :identifier, :role, :audiences
|
|
4
|
+
|
|
5
|
+
def initialize(parsed_response)
|
|
6
|
+
@parsed_response = parsed_response
|
|
7
|
+
|
|
8
|
+
@identifier = @parsed_response.fetch("id", nil)
|
|
9
|
+
@role = build_role
|
|
10
|
+
@audiences = build_audiences
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def to_permissions
|
|
14
|
+
@audiences.map { Permission.new(identifier: @identifier, role: @role, audience: it) }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def build_role
|
|
20
|
+
roles = @parsed_response.fetch("roles", [])
|
|
21
|
+
roles.is_a?(Array) ? roles.first : roles
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def build_audiences
|
|
25
|
+
audiences = []
|
|
26
|
+
|
|
27
|
+
audiences += audiences_from_site_users
|
|
28
|
+
audiences += audiences_from_anonymous_links
|
|
29
|
+
|
|
30
|
+
audiences.compact
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def audiences_from_site_users
|
|
34
|
+
site_users = []
|
|
35
|
+
site_users += @parsed_response.fetch("grantedToIdentitiesV2", []).flat_map { it.fetch("siteUser", nil) }
|
|
36
|
+
site_users << @parsed_response.dig("grantedToV2", "siteUser")
|
|
37
|
+
site_users.compact!
|
|
38
|
+
|
|
39
|
+
site_users.map { Audience.from_site_user(it) }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def audiences_from_anonymous_links
|
|
43
|
+
link = @parsed_response.fetch("link", nil)
|
|
44
|
+
return [] if link.nil? || (link.respond_to?(:empty?) && link.empty?)
|
|
45
|
+
|
|
46
|
+
link_scope = link.fetch("scope", nil)
|
|
47
|
+
|
|
48
|
+
return [] unless link_scope == "anonymous" # I.e. an "anyone with the link" audience
|
|
49
|
+
|
|
50
|
+
[
|
|
51
|
+
Audience.new(
|
|
52
|
+
type: "anyone",
|
|
53
|
+
identifier: "anyone_with_the_link",
|
|
54
|
+
display_name: "Anyone with the link",
|
|
55
|
+
email_address: nil
|
|
56
|
+
)
|
|
57
|
+
]
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module MicroslopOneDrive
|
|
2
|
+
class PermissionList < ListResponse
|
|
3
|
+
attr_reader :permissions
|
|
4
|
+
|
|
5
|
+
def initialize(parsed_response)
|
|
6
|
+
super(parsed_response)
|
|
7
|
+
|
|
8
|
+
@parsed_response = parsed_response
|
|
9
|
+
@permissions = build_permissions
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def build_permissions
|
|
15
|
+
value_list = @parsed_response.is_a?(Array) ? @parsed_response : @parsed_response.fetch("value", [])
|
|
16
|
+
permission_batches = value_list.map { MicroslopOneDrive::PermissionBatch.new(it) }
|
|
17
|
+
|
|
18
|
+
# At this stage, the permissions could contain multiple Audiences for the same Permission.
|
|
19
|
+
# This is because OneDrive can return multiple permissions for the same thing.
|
|
20
|
+
# For example, a file shared with one person and a public link will return in a single permission object.
|
|
21
|
+
# We therefore need to "explode" the permissions into multiple permissions, one for each Audience.
|
|
22
|
+
permission_batches.flat_map(&:to_permissions)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module MicroslopOneDrive
|
|
2
|
+
class User
|
|
3
|
+
attr_reader :email_address, :display_name
|
|
4
|
+
|
|
5
|
+
def initialize(user_hash)
|
|
6
|
+
@user_hash = user_hash
|
|
7
|
+
|
|
8
|
+
@email_address = @user_hash.fetch("mail", nil)
|
|
9
|
+
@display_name = @user_hash.fetch("displayName", nil)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require "httparty"
|
|
2
|
+
require "json"
|
|
3
|
+
|
|
4
|
+
require_relative "microslop_one_drive/version"
|
|
5
|
+
require_relative "microslop_one_drive/utils"
|
|
6
|
+
require_relative "microslop_one_drive/errors/client_error"
|
|
7
|
+
require_relative "microslop_one_drive/user"
|
|
8
|
+
require_relative "microslop_one_drive/list_response"
|
|
9
|
+
require_relative "microslop_one_drive/drive_list"
|
|
10
|
+
require_relative "microslop_one_drive/drive"
|
|
11
|
+
require_relative "microslop_one_drive/drive_item"
|
|
12
|
+
require_relative "microslop_one_drive/drive_item_list"
|
|
13
|
+
require_relative "microslop_one_drive/permission_list"
|
|
14
|
+
require_relative "microslop_one_drive/permission_batch"
|
|
15
|
+
require_relative "microslop_one_drive/permission"
|
|
16
|
+
require_relative "microslop_one_drive/audience"
|
|
17
|
+
require_relative "microslop_one_drive/client"
|
metadata
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: microslop_one_drive
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Bradley Marques
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: httparty
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0.24'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0.24'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: minitest
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '5'
|
|
33
|
+
type: :development
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '5'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: mocha
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '2'
|
|
47
|
+
type: :development
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '2'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: rake
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '13'
|
|
61
|
+
type: :development
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '13'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: rubocop
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - "~>"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '1'
|
|
75
|
+
type: :development
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - "~>"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '1'
|
|
82
|
+
description: Lightweight value objects and HTTP client for OneDrive delta sync, item
|
|
83
|
+
metadata, and sharing permissions.
|
|
84
|
+
email:
|
|
85
|
+
- ''
|
|
86
|
+
executables: []
|
|
87
|
+
extensions: []
|
|
88
|
+
extra_rdoc_files: []
|
|
89
|
+
files:
|
|
90
|
+
- LICENSE.txt
|
|
91
|
+
- README.md
|
|
92
|
+
- lib/microslop_one_drive.rb
|
|
93
|
+
- lib/microslop_one_drive/audience.rb
|
|
94
|
+
- lib/microslop_one_drive/client.rb
|
|
95
|
+
- lib/microslop_one_drive/drive.rb
|
|
96
|
+
- lib/microslop_one_drive/drive_item.rb
|
|
97
|
+
- lib/microslop_one_drive/drive_item_list.rb
|
|
98
|
+
- lib/microslop_one_drive/drive_list.rb
|
|
99
|
+
- lib/microslop_one_drive/errors/client_error.rb
|
|
100
|
+
- lib/microslop_one_drive/list_response.rb
|
|
101
|
+
- lib/microslop_one_drive/permission.rb
|
|
102
|
+
- lib/microslop_one_drive/permission_batch.rb
|
|
103
|
+
- lib/microslop_one_drive/permission_list.rb
|
|
104
|
+
- lib/microslop_one_drive/user.rb
|
|
105
|
+
- lib/microslop_one_drive/utils.rb
|
|
106
|
+
- lib/microslop_one_drive/version.rb
|
|
107
|
+
homepage: https://github.com/bradleymarques/microslop_one_drive
|
|
108
|
+
licenses:
|
|
109
|
+
- MIT
|
|
110
|
+
metadata:
|
|
111
|
+
homepage_uri: https://github.com/bradleymarques/microslop_one_drive
|
|
112
|
+
source_code_uri: https://github.com/bradleymarques/microslop_one_drive
|
|
113
|
+
rdoc_options: []
|
|
114
|
+
require_paths:
|
|
115
|
+
- lib
|
|
116
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
117
|
+
requirements:
|
|
118
|
+
- - ">="
|
|
119
|
+
- !ruby/object:Gem::Version
|
|
120
|
+
version: 3.4.2
|
|
121
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
122
|
+
requirements:
|
|
123
|
+
- - ">="
|
|
124
|
+
- !ruby/object:Gem::Version
|
|
125
|
+
version: '0'
|
|
126
|
+
requirements: []
|
|
127
|
+
rubygems_version: 3.7.2
|
|
128
|
+
specification_version: 4
|
|
129
|
+
summary: Ruby client helpers for Microsoft Graph OneDrive/SharePoint API (drive items,
|
|
130
|
+
delta, permissions).
|
|
131
|
+
test_files: []
|