Skip to content

Commit

Permalink
Changed tokens to be handled externally, CI fixes, and fixed package …
Browse files Browse the repository at this point in the history
…structure
  • Loading branch information
Rasmus Oscar Welander committed Aug 29, 2024
1 parent afe7044 commit 6c955c3
Show file tree
Hide file tree
Showing 30 changed files with 463 additions and 403 deletions.
8 changes: 7 additions & 1 deletion .github/workflows/ci-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,13 @@ jobs:
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide, we further relax this
flake8 . --count --exit-zero --max-complexity=30 --max-line-length=130 --statistics
- name: Build
run: |
pip install build
python -m build
- name: Install
run: |
pip install .
- name: Test with pytest
run: |
if [ -f tests/requirements.txt ]; then pip install -r tests/requirements.txt; fi
Expand Down
81 changes: 45 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ Alternatively, you can clone this repository and install manually:
```bash
git clone [email protected]:cs3org/cs3-python-client.git
cd cs3-python-client
pip install -e .
export PYTHONPATH="path/to/cs3-python-client/:$PYTHONPATH"
pip install .
```


Expand Down Expand Up @@ -112,129 +111,136 @@ lock_expiration = 1800

To use `cs3client`, you first need to import and configure it. Here's a simple example of how to set up and start using the client. For configuration see [Configuration](#configuration). For more in depth examples see `cs3-python-client/examples/`.

### Initilization
### Initilization and Authentication
```python
import logging
import configparser
from cs3client import CS3Client
from cs3resource import Resource
from cs3client.cs3client import CS3Client

config = configparser.ConfigParser()
with open("default.conf") as fdef:
config.read_file(fdef)

log = logging.getLogger(__name__)

client = CS3Client(config, "cs3client", log)
# client.auth.set_token("<your_token_here>")
# OR

# Set client secret
client.auth.set_client_secret("<your_client_secret_here>")
# Checks if token is expired if not return ('x-access-token', <token>)
# if expired, request a new token from reva
auth_token = client.auth.get_token()

# OR if you already have a reva token
# Checks if token is expired if not return (x-access-token', <token>)
# if expired, throws an AuthenticationException (so you can refresh your reva token)
token = "<your_reva_token>"
auth_token = client.auth.check_token(token)
```

### File Example
```python
# mkdir
directory_resource = Resource.from_file_ref_and_endpoint(f"/eos/user/r/rwelande/test_directory")
res = client.file.make_dir(directory_resource)
res = client.file.make_dir(client.auth.get_token(), directory_resource)

# touchfile
touch_resource = Resource.from_file_ref_and_endpoint("/eos/user/r/rwelande/touch_file.txt")
res = client.file.touch_file(touch_resource)
res = client.file.touch_file(client.auth.get_token(), touch_resource)

# setxattr
resource = Resource.from_file_ref_and_endpoint("/eos/user/r/rwelande/text_file.txt")
res = client.file.set_xattr(resource, "iop.wopi.lastwritetime", str(1720696124))
res = client.file.set_xattr(client.auth.get_token(), resource, "iop.wopi.lastwritetime", str(1720696124))

# rmxattr
res = client.file.remove_xattr(resource, "iop.wopi.lastwritetime")
res = client.file.remove_xattr(client.auth.get_token(), resource, "iop.wopi.lastwritetime")

# stat
res = client.file.stat(resource)
res = client.file.stat(client.auth.get_token(), resource)

# removefile
res = client.file.remove_file(touch_resource)
res = client.file.remove_file(client.auth.get_token(), touch_resource)

# rename
rename_resource = Resource.from_file_ref_and_endpoint("/eos/user/r/rwelande/rename_file.txt")
res = client.file.rename_file(resource, rename_resource)
res = client.file.rename_file(client.auth.get_token(), resource, rename_resource)

# writefile
content = b"Hello World"
size = len(content)
res = client.file.write_file(rename_resource, content, size)
res = client.file.write_file(client.auth.get_token(), rename_resource, content, size)

# listdir
list_directory_resource = Resource.from_file_ref_and_endpoint("/eos/user/r/rwelande")
res = client.file.list_dir(list_directory_resource)
res = client.file.list_dir(client.auth.get_token(), list_directory_resource)


# readfile
file_res = client.file.read_file(rename_resource)
file_res = client.file.read_file(client.auth.get_token(), rename_resource)
```

### Share Example
```python
# Create share #
resource = Resource.from_file_ref_and_endpoint("/eos/user/r/<some_username>/text.txt")
resource_info = client.file.stat(resource)
resource_info = client.file.stat(client.auth.get_token(), resource)
user = client.user.get_user_by_claim("username", "<some_username>")
res = client.share.create_share(resource_info, user.id.opaque_id, user.id.idp, "EDITOR", "USER")
res = client.share.create_share(client.auth.get_token(), resource_info, user.id.opaque_id, user.id.idp, "EDITOR", "USER")

# List existing shares #
filter_list = []
filter = client.share.create_share_filter(resource_id=resource_info.id, filter_type="TYPE_RESOURCE_ID")
filter_list.append(filter)
filter = client.share.create_share_filter(share_state="SHARE_STATE_PENDING", filter_type="TYPE_STATE")
filter_list.append(filter)
res, _ = client.share.list_existing_shares()
res, _ = client.share.list_existing_shares(client.auth.get_token(), )

# Get share #
share_id = "58"
res = client.share.get_share(opaque_id=share_id)
res = client.share.get_share(client.auth.get_token(), opaque_id=share_id)

# update share #
res = client.share.update_share(opaque_id=share_id, role="VIEWER")
res = client.share.update_share(client.auth.get_token(), opaque_id=share_id, role="VIEWER")

# remove share #
res = client.share.remove_share(opaque_id=share_id)
res = client.share.remove_share(client.auth.get_token(), opaque_id=share_id)

# List existing received shares #
filter_list = []
filter = client.share.create_share_filter(share_state="SHARE_STATE_ACCEPTED", filter_type="TYPE_STATE")
filter_list.append(filter)
res, _ = client.share.list_received_existing_shares()
res, _ = client.share.list_received_existing_shares(client.auth.get_token())

# get received share #
received_share = client.share.get_received_share(opaque_id=share_id)
received_share = client.share.get_received_share(client.auth.get_token(), opaque_id=share_id)

# update recieved share #
res = client.share.update_received_share(received_share=received_share, state="SHARE_STATE_ACCEPTED")
res = client.share.update_received_share(client.auth.get_token(), received_share=received_share, state="SHARE_STATE_ACCEPTED")

# create public share #
res = client.share.create_public_share(resource_info, role="VIEWER")
res = client.share.create_public_share(client.auth.get_token(), resource_info, role="VIEWER")

# list existing public shares #
filter_list = []
filter = client.share.create_public_share_filter(resource_id=resource_info.id, filter_type="TYPE_RESOURCE_ID")
filter_list.append(filter)
res, _ = client.share.list_existing_public_shares(filter_list=filter_list)

res = client.share.get_public_share(opaque_id=share_id, sign=True)
res = client.share.get_public_share(client.auth.get_token(), opaque_id=share_id, sign=True)
# OR token = "<token>"
# res = client.share.get_public_share(token=token, sign=True)

# update public share #
res = client.share.update_public_share(type="TYPE_PASSWORD", token=token, role="VIEWER", password="hello")
res = client.share.update_public_share(client.auth.get_token(), type="TYPE_PASSWORD", token=token, role="VIEWER", password="hello")

# remove public share #
res = client.share.remove_public_share(token=token)
res = client.share.remove_public_share(client.auth.get_token(), token=token)

```

### User Example
```python
# find_user
res = client.user.find_users("rwel")
res = client.user.find_users(client.auth.get_token(), "rwel")

# get_user
res = client.user.get_user("https://auth.cern.ch/auth/realms/cern", "asdoiqwe")
Expand All @@ -253,21 +259,21 @@ res = client.user.get_user_by_claim("username", "rwelande")
### App Example
```python
# list_app_providers
res = client.app.list_app_providers()
res = client.app.list_app_providers(client.auth.get_token())

# open_in_app
resource = Resource.from_file_ref_and_endpoint("/eos/user/r/rwelande/collabora.odt")
res = client.app.open_in_app(resource)
res = client.app.open_in_app(client.auth.get_token(), resource)
```

### Checkpoint Example
```python
# list file versions
resource = Resource.from_file_ref_and_endpoint("/eos/user/r/rwelande/test.md")
res = client.checkpoint.list_file_versions(resource)
res = client.checkpoint.list_file_versions(client.auth.get_token(), resource)

# restore file version
res = client.checkpoint.restore_file_version(resource, "1722936250.0569fa2f")
res = client.checkpoint.restore_file_version(client.auth.get_token(), resource, "1722936250.0569fa2f")
```

## Documentation
Expand All @@ -282,6 +288,9 @@ make html
## Unit tests

```bash
# install library
pip install .
# run unit tests
pytest --cov-report term --cov=serc tests/
```

Expand Down
File renamed without changes.
25 changes: 13 additions & 12 deletions src/app.py → cs3client/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@
Authors: Rasmus Welander, Diogo Castro, Giuseppe Lo Presti.
Emails: [email protected], [email protected], [email protected]
Last updated: 19/08/2024
Last updated: 28/08/2024
"""

import logging
from auth import Auth
from cs3resource import Resource
import cs3.app.registry.v1beta1.registry_api_pb2 as cs3arreg
import cs3.app.registry.v1beta1.resources_pb2 as cs3arres
import cs3.gateway.v1beta1.gateway_api_pb2 as cs3gw
import cs3.app.provider.v1beta1.resources_pb2 as cs3apr
from cs3.gateway.v1beta1.gateway_api_pb2_grpc import GatewayAPIStub
from statuscodehandler import StatusCodeHandler
from config import Config

from cs3client.cs3resource import Resource
from cs3client.statuscodehandler import StatusCodeHandler
from cs3client.config import Config


class App:
Expand All @@ -28,7 +28,6 @@ def __init__(
config: Config,
log: logging.Logger,
gateway: GatewayAPIStub,
auth: Auth,
status_code_handler: StatusCodeHandler,
) -> None:
"""
Expand All @@ -37,20 +36,21 @@ def __init__(
:param config: Config object containing the configuration parameters.
:param log: Logger instance for logging.
:param gateway: GatewayAPIStub instance for interacting with CS3 Gateway.
:param auth: An instance of the auth class.
:param status_code_handler: An instance of the StatusCodeHandler class.
"""
self._status_code_handler: StatusCodeHandler = status_code_handler
self._gateway: GatewayAPIStub = gateway
self._log: logging.Logger = log
self._config: Config = config
self._auth: Auth = auth

def open_in_app(self, resource: Resource, view_mode: str = None, app: str = None) -> cs3apr.OpenInAppURL:
def open_in_app(
self, auth_token: tuple, resource: Resource, view_mode: str = None, app: str = None
) -> cs3apr.OpenInAppURL:
"""
Open a file in an app, given the resource, view mode (VIEW_MODE_VIEW_ONLY, VIEW_MODE_READ_ONLY,
VIEW_MODE_READ_WRITE, VIEW_MODE_PREVIEW), and app name.
:param auth_token: tuple in the form ('x-access-token', <token> (see auth.get_token/auth.check_token)
:param resource: Resource object containing the resource information.
:param view_mode: View mode of the app.
:param app: App name.
Expand All @@ -63,21 +63,22 @@ def open_in_app(self, resource: Resource, view_mode: str = None, app: str = None
if view_mode:
view_mode_type = cs3gw.OpenInAppRequest.ViewMode.Value(view_mode)
req = cs3gw.OpenInAppRequest(ref=resource.ref, view_mode=view_mode_type, app=app)
res = self._gateway.OpenInApp(request=req, metadata=[self._auth.get_token()])
res = self._gateway.OpenInApp(request=req, metadata=[auth_token])
self._status_code_handler.handle_errors(res.status, "open in app", f"{resource.get_file_ref_str()}")
self._log.debug(f'msg="Invoked OpenInApp" {resource.get_file_ref_str()} trace="{res.status.trace}"')
return res.OpenInAppURL

def list_app_providers(self) -> list[cs3arres.ProviderInfo]:
def list_app_providers(self, auth_token: dict) -> list[cs3arres.ProviderInfo]:
"""
list_app_providers lists all the app providers.
:param auth_token: tuple in the form ('x-access-token', <token> (see auth.get_token/auth.check_token)
:return: List of app providers.
:raises: AuthenticationException (Operation not permitted)
:raises: UnknownException (Unknown error)
"""
req = cs3arreg.ListAppProvidersRequest()
res = self._gateway.ListAppProviders(request=req, metadata=[self._auth.get_token()])
res = self._gateway.ListAppProviders(request=req, metadata=[auth_token])
self._status_code_handler.handle_errors(res.status, "list app providers")
self._log.debug(f'msg="Invoked ListAppProviders" res_count="{len(res.providers)}" trace="{res.status.trace}"')
return res.providers
Loading

0 comments on commit 6c955c3

Please sign in to comment.