-
Notifications
You must be signed in to change notification settings - Fork 137
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Map Discord roles to NextCloud groups #395
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -79,6 +79,7 @@ class ProviderService | |
'id' => 'appid', | ||
'secret' => 'secret', | ||
], | ||
'group_mapping' => 'groupMapping', | ||
], | ||
self::TYPE_OPENID => [ | ||
'openid_identifier' => 'url', | ||
|
@@ -232,7 +233,7 @@ public function handleDefault($provider) | |
{ | ||
$config = []; | ||
$scopes = [ | ||
'discord' => 'identify email guilds', | ||
'discord' => 'identify email guilds guilds.members.read', | ||
]; | ||
$providers = json_decode($this->config->getAppValue($this->appName, 'oauth_providers'), true) ?: []; | ||
if (is_array($providers) && in_array($provider, array_keys($providers))) { | ||
|
@@ -413,6 +414,24 @@ private function auth($class, array $config, $provider, $providerType = null) | |
throw new LoginException($this->l->t('Login is available only to members of the following Discord guilds: %s', $config['guilds'])); | ||
}; | ||
$checkGuilds(); | ||
|
||
// read Discord roles into NextCloud groups | ||
$profile->data['groups'] = []; | ||
if(!empty($allowedGuilds)) { | ||
foreach($userGuilds as $guild) { | ||
if (!in_array($guild->id ?? null, $allowedGuilds)) { | ||
// Only read groups from the explicitly declared guilds. | ||
// It doesn't make sense to try to map in random, unknown groups from arbitrary guilds. | ||
// and without this, a user in many guilds will trip a HTTP 429 rate limit from the Discord API. | ||
continue; | ||
} | ||
# https://discord.com/developers/docs/resources/guild#get-guild-member | ||
$guild_data = $adapter->apiRequest('users/@me/guilds/' . $guild->id . '/member' ); | ||
$profile->data['groups'] = array_merge($profile->data['groups'], $guild_data->roles ?? []); | ||
// TODO: /member returns roles as their ID; to get their name requires an extra API call | ||
// (and perhaps extra permissions?) | ||
} | ||
} | ||
} | ||
|
||
if (!empty($config['logout_url'])) { | ||
|
@@ -422,6 +441,7 @@ private function auth($class, array $config, $provider, $providerType = null) | |
} | ||
|
||
$profile->data['default_group'] = $config['default_group']; | ||
$profile->data['group_mapping'] = $config['group_mapping']; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this need to be wrapped in an |
||
|
||
if ($provider === 'telegram') { | ||
$provider = 'tg'; //For backward compatibility | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -120,6 +120,20 @@ | |
<input type="text" :name="'providers['+name+'][guilds]'" v-model="provider.guilds"/> | ||
</label> | ||
</template> | ||
<template v-if="provider.hasGroupMapping"> | ||
<button class="group-mapping-add" type="button" @click="provider.groupMapping.push({foreign: '', local: ''})"> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
{{ t(appName, 'Add group mapping') }} | ||
</button> | ||
<div v-for="(mapping, mappingIdx) in provider.groupMapping" :key="mapping"> | ||
<input type="text" class="foreign-group" v-model="mapping.foreign" /> | ||
<select class="local-group" :name="mapping.foreign ? 'providers['+name+'][groupMapping]['+mapping.foreign+']' : ''"> | ||
<option v-for="group in groups" :key="group" :value="group" :selected="mapping.local === group"> | ||
{{ group }} | ||
</option> | ||
</select> | ||
<span class="group-mapping-remove" @click="provider.groupMapping.splice(mappingIdx, 1)">x</span> | ||
</div> | ||
</template> | ||
Comment on lines
+123
to
+136
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This code is also copy-pasted!! |
||
</div> | ||
<br/> | ||
|
||
|
@@ -148,6 +162,10 @@ export default { | |
data.custom_providers = {} | ||
} | ||
|
||
// In the 'custom' providers, those that can have multiple instances of the same protocol, rewrite groupMapping | ||
// from { foreign0: local0, foreign1, local1, ... } | ||
// to [ { 'foreign': foreign0, 'local': local0 }, { 'foreign': foreign1, 'local': local1 }, ... ] | ||
// This is necessary for Vue to use groupMapping as a read-write data model. | ||
for (var provType in providerTypes) { | ||
if (!data.custom_providers[provType]) { | ||
data.custom_providers[provType] = [] | ||
|
@@ -165,6 +183,24 @@ export default { | |
} | ||
} | ||
} | ||
|
||
// For the fixed providers, with only a singleton instance of the login server, rewrite groupMapping | ||
// from { foreign0: local0, foreign1, local1, ... } | ||
// to [ { 'foreign': foreign0, 'local': local0 }, { 'foreign': foreign1, 'local': local1 }, ... ] | ||
// This is necessary for Vue to use groupMapping as a read-write data model. | ||
for (var provType in data.providers) { | ||
if (data.providers[provType].hasGroupMapping) { | ||
var groupMappingArr = [] | ||
var groupMapping = data.providers[provType].groupMapping | ||
if (groupMapping) { | ||
for (var foreignGroup in groupMapping) { | ||
groupMappingArr.push({foreign: foreignGroup, local: groupMapping[foreignGroup]}) | ||
Comment on lines
+193
to
+197
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This code is copy-pasted!! 💢 |
||
} | ||
} | ||
data.providers[provType].groupMapping = groupMappingArr | ||
} | ||
} | ||
|
||
data.appName = appName | ||
return data | ||
}, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand what
$configMapping
is about. We control the schema, can't we just force all the providers to use the same one?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hybridauth is external lib
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It just works as it should. I think with the little Tutorial, everyone can set this up!