I created a seafile server and used Keycloak as an authentication provider. I made a script to create groups in seafile using groups from Keycloak and adding seafile users to those groups, according to their membership in Keycloak. I used seafile WebApi to do that, but anytime I run the code I get the following error:
Error adding user 'xxxxx@auth.local' to group '29':b'{"error_msg":"Email invalid."}'
I checked hat the email address is exactly the one in seafile used as an ID and not the contact_email. The previous lines to create the group works, so it can’t be a problem of reaching the wrong server.
When I try to do it from the command line for an existing group where the user is not, I get the following error:
$ curl -d "email=xxxxxx@auth.local" -H 'accept: application/json' -H 'authorization: Bearer <token>' -H 'content-type: application/json' http://localhost:8001/api/v2.1/admin/groups/1/members/
{"detail":"JSON parse error - Expecting value: line 1 column 1 (char 0)"}
And when I check the seahub.log logs, I have only a django Bad Request warning:
[WARNING] django.request:241 log_response Bad Request: /api/v2.1/admin/groups/30/members/
I would like to know if there is a solution to my problem/something I have not seen or considered.
Here is the code I’m using to “copy/paste” the groups from Keycloak
import requests
import pymysql
KEYCLOAK_ADMIN_URL=f"http://{KEYCLOAK_URL}/realms/master/protocol/openid-connect/token"
KEYCLOAK_BASE_URL= f"http://{KEYCLOAK_URL}/admin/realms/myrealm"
SEAFILE_API_TOKEN=<token>
database_connection = pymysql.connect(user="root", password=<password>, host=<host>)
def get_keycloak_token():
data = {'client_id':"admin-cli", 'client_secret':<client_secret>, 'grant_type':'client_credentials'}
response = requests.post(KEYCLOAK_ADMIN_URL, data=data)
response.raise_for_status()
return response.json()['access_token']
def get_keycloak_groups(token):
headers = {'Authorization':f'Bearer {token}'}
response = requests.get(f"{KEYCLOAK_BASE_URL}/groups", headers=headers)
return response.json()
def get_group_members(token, group_id):
headers = {'Authorization':f'Bearer {token}'}
response = requests.get(f"{KEYCLOAK_BASE_URL}/groups/{group_id}/members", headers=headers)
return response.json()
def create_seafile_groups(group_name):
headers = {'Authorization':f'Bearer {SEAFILE_API_TOKEN}', 'Accept':'application/json', 'charset':'utf-8', 'indent':'4'}
print(type(group_name))
data = {'group_name':group_name}
response = requests.post(f"{SEAFILE_BASE_URL}/groups/", headers=headers, json=data)
if 'error' in response:
return response.json()
return response.json()
def add_user_to_seafile_group(group_id, seafile_id):
headers = {'Authorization':f'Bearer {SEAFILE_API_TOKEN}', 'Accept':'application/json', 'content-type':'application/json'}
data = {'email':seafile_id}
response = requests.post(f"{SEAFILE_BASE_URL}/groups/{group_id}/members/", headers=headers, json=data)
if response.status_code != 200 and response.status_code!=201:
print(f"Error adding user '{seafile_id}' to group '{group_id}':{response.content}")
def db_add_user_to_seafile_group(connection, group_id, seafile_id):
cursor = connection.cursor()
def seafile_id_from_keycloak_id(user_id,connection):
cursor = connection.cursor()
cursor.execute("USE `seahub_db`")
cursor.execute(f"""
SELECT username FROM social_auth_usersocialauth
WHERE uid = '{user_id}'
""")
seafile_id = cursor.fetchone()[0]
return seafile_id
def main(connection):
keycloak_token=get_keycloak_token()
groups=get_keycloak_groups(keycloak_token)
for group in groups:
group_name = group["name"]
group_id=group["id"]
seafile_group=create_seafile_groups(group_name)
seafile_group_id=seafile_group['id']
members=get_group_members(keycloak_token,group_id)
for member in members:
print(member)
user_id=member.get('id')
if user_id:
seafile_user_id=seafile_id_from_keycloak_id(user_id,connection)
add_user_to_seafile_group(seafile_group_id,seafile_user_id)
else:
print(f"User {member['username']} does not have an id. Skipping.")
main(database_connection)
database_connection.close()