updating teams from oidc possible, fixed undefined error, no need for extra login to assign/create teams/orgs

This commit is contained in:
viehlieb 2022-03-10 15:56:35 +01:00
parent 263b405fc8
commit f90875d8ef
5 changed files with 143 additions and 61 deletions

View file

@ -209,7 +209,31 @@ if (Meteor.isServer) {
});
}
},
setOrgAllFieldsFromOidc(
org,
orgDisplayName,
orgDesc,
orgShortName,
orgWebsite,
orgIsActive,
) {
check(org, Object);
check(orgDisplayName, String);
check(orgDesc, String);
check(orgShortName, String);
check(orgWebsite, String);
check(orgIsActive, Boolean);
Org.update(org, {
$set: {
orgDisplayName: orgDisplayName,
orgDesc: orgDesc,
orgShortName: orgShortName,
orgWebsite: orgWebsite,
orgIsActive: orgIsActive,
},
});
Meteor.call('setUsersOrgsOrgDisplayName', org._id, orgDisplayName);
},
setOrgAllFields(
org,
orgDisplayName,

View file

@ -206,7 +206,31 @@ if (Meteor.isServer) {
});
}
},
setTeamAllFieldsFromOidc(
team,
teamDisplayName,
teamDesc,
teamShortName,
teamWebsite,
teamIsActive,
) {
check(team, Object);
check(teamDisplayName, String);
check(teamDesc, String);
check(teamShortName, String);
check(teamWebsite, String);
check(teamIsActive, Boolean);
Team.update(team, {
$set: {
teamDisplayName: teamDisplayName,
teamDesc: teamDesc,
teamShortName: teamShortName,
teamWebsite: teamWebsite,
teamIsActive: teamIsActive,
},
});
Meteor.call('setUsersTeamsTeamDisplayName', team._id, teamDisplayName);
},
setTeamAllFields(
team,
teamDisplayName,

View file

@ -214,6 +214,11 @@ class KnownUser {
}
static onLogin(loginInfo) {
//get the data from oidc login and remove again?
if(loginInfo.type ==='oidc'){
Meteor.call('groupRoutineOnLogin', loginInfo.user.services.oidc, loginInfo.user._id);
return;
}
if (loginInfo.type !== 'password') {
return;
}

View file

@ -13,6 +13,18 @@ function createObject(initArr, objString)
initArr[4]//xxxisActive
);
}
function updateObject(initArr, objString)
{
functionName = objString === "Org" ? 'setOrgAllFieldsFromOidc' : 'setTeamAllFieldsFromOidc';
return Meteor.call(functionName,
initArr[0],//team || org Object
initArr[1],//displayName
initArr[2],//desc
initArr[3],//shortName
initArr[4],//website
initArr[5]//xxxisActive
);
}
//checks whether obj is in collection of userObjs
//params
//e.g. userObjs = user.teams
@ -22,7 +34,7 @@ function contains(userObjs, obj, collection)
{
id = collection+'Id';
if(!userObjs.length)
if(typeof userObjs == "undefined" || !userObjs.length)
{
return false;
}
@ -36,30 +48,6 @@ function contains(userObjs, obj, collection)
return false;
}
module.exports = {
// Soft version of adding teams to user via Oidc
// teams won't be created if nonexistent
// groups are treated as teams in the general case
addGroups: function (user, groups){
teamArray=[];
teams = user.teams;
orgArray=[];
for (group of groups){
team = Team.findOne({"teamDisplayName": group});
if(team)
{
if (contains(teams,team,"team"))
{
continue;
}
else
{
teamArray.push({'teamId': Team.findOne({'teamDisplayName': group})._id, 'teamDisplayName': group});
}
}
}
teams = {'teams': { '$each': teamArray}};
users.update({ _id: user._id }, { $push: teams});
},
// This function adds groups as organizations or teams to users and
// creates them if not already existing
@ -72,12 +60,20 @@ module.exports = {
addGroupsWithAttributes: function (user, groups){
teamArray=[];
orgArray=[];
isAdmin = [];
teams = user.teams;
orgs = user.orgs;
for (group of groups)
{
initAttributes = [
group.displayName,
group.desc || group.displayName,
group.shortName ||group.displayName,
group.website || group.displayName, group.isActive || false];
isOrg = group.isOrganisation || false;
forceCreate = group.forceCreate|| false;
isAdmin.push(group.isAdmin || false);
if (isOrg)
{
org = Org.findOne({"orgDisplayName": group.displayName});
@ -85,16 +81,13 @@ addGroupsWithAttributes: function (user, groups){
{
if(contains(orgs, org, "org"))
{
initAttributes.unshift(org);
updateObject(initAttributes, "Org");
continue;
}
}
else if(forceCreate)
{
initAttributes = [
group.displayName,
group.desc || group.displayName,
group.shortName ||group.displayName,
group.website || group.displayName, group.isActive || false]
createObject(initAttributes, "Org");
org = Org.findOne({'orgDisplayName': group.displayName});
}
@ -114,17 +107,13 @@ addGroupsWithAttributes: function (user, groups){
{
if(contains(teams, team, "team"))
{
initAttributes.unshift(team);
updateObject(initAttributes, "Team");
continue;
}
}
else if(forceCreate)
{
initAttributes = [
group.displayName,
group.desc || group.displayName,
group.shortName ||group.displayName,
group.website || group.displayName,
group.isActive || false]
createObject(initAttributes, "Team");
team = Team.findOne({'teamDisplayName': group.displayName});
}
@ -135,16 +124,19 @@ addGroupsWithAttributes: function (user, groups){
teamHash = {'teamId': team._id, 'teamDisplayName': group.displayName};
teamArray.push(teamHash);
}
// user is assigned to group which has set isAdmin: true in oidc data
// hence user will get admin privileges in wekan
if(group.isAdmin){
users.update({ _id: user._id }, { $set: {isAdmin: true}});
}
}
// user is assigned to team/org which has set isAdmin: true in oidc data
// hence user will get admin privileges in wekan
// E.g. Admin rights will be withdrawn if no group in oidc provider has isAdmin set to true
users.update({ _id: user._id }, { $set: {isAdmin: isAdmin.some(i => (i === true))}});
teams = {'teams': {'$each': teamArray}};
orgs = {'orgs': {'$each': orgArray}};
users.update({ _id: user._id }, { $push: teams});
users.update({ _id: user._id }, { $push: orgs});
// remove temporary oidc data from user collection
users.update({ _id: user._id }, { $unset: {"services.oidc.groups": []}});
return;
},

View file

@ -1,4 +1,4 @@
import {addGroups, addGroupsWithAttributes, addEmail, changeFullname, changeUsername} from './loginHandler';
import {addGroupsWithAttributes, addEmail, changeFullname, changeUsername} from './loginHandler';
Oidc = {};
httpCa = false;
@ -14,11 +14,13 @@ if (process.env.OAUTH2_CA_CERT !== undefined) {
console.log(e);
}
}
var profile = {};
var serviceData = {};
var userinfo = {};
OAuth.registerService('oidc', 2, null, function (query) {
var debug = process.env.DEBUG || false;
var propagateOidcData = process.env.PROPAGATE_OIDC_DATA || false;
var token = getToken(query);
if (debug) console.log('XXX: register token:', token);
@ -28,7 +30,6 @@ OAuth.registerService('oidc', 2, null, function (query) {
var claimsInAccessToken = (process.env.OAUTH2_ADFS_ENABLED === 'true' || process.env.OAUTH2_ADFS_ENABLED === true) || false;
var userinfo;
if(claimsInAccessToken)
{
// hack when using custom claims in the accessToken. On premise ADFS
@ -44,13 +45,13 @@ OAuth.registerService('oidc', 2, null, function (query) {
if (userinfo.metadata) userinfo = userinfo.metadata // Openshift hack
if (debug) console.log('XXX: userinfo:', userinfo);
var serviceData = {};
serviceData.id = userinfo[process.env.OAUTH2_ID_MAP]; // || userinfo["id"];
serviceData.username = userinfo[process.env.OAUTH2_USERNAME_MAP]; // || userinfo["uid"];
serviceData.fullname = userinfo[process.env.OAUTH2_FULLNAME_MAP]; // || userinfo["displayName"];
serviceData.accessToken = accessToken;
serviceData.expiresAt = expiresAt;
// If on Oracle OIM email is empty or null, get info from username
if (process.env.ORACLE_OIM_ENABLED === 'true' || process.env.ORACLE_OIM_ENABLED === true) {
if (userinfo[process.env.OAUTH2_EMAIL_MAP]) {
@ -74,24 +75,37 @@ OAuth.registerService('oidc', 2, null, function (query) {
serviceData.refreshToken = token.refresh_token;
if (debug) console.log('XXX: serviceData:', serviceData);
var profile = {};
profile.name = userinfo[process.env.OAUTH2_FULLNAME_MAP]; // || userinfo["displayName"];
profile.email = userinfo[process.env.OAUTH2_EMAIL_MAP]; // || userinfo["email"];
if (propagateOidcData)
{
users= Meteor.users;
user = users.findOne({'services.oidc.id': serviceData.id});
if(user)
{
(!userinfo?.["wekanGroups"]?.length) ? addGroups(user, userinfo["groups"]): addGroupsWithAttributes(user, userinfo["wekanGroups"]);
if(profile.email) addEmail(user, profile.email);
if(profile.name) changeFullname(user, profile.name);
if(profile.username) changeUsername(user, profile.username);
}
}
if (debug) console.log('XXX: profile:', profile);
//temporarily store data from oidc in user.services.oidc.groups to update groups
serviceData.groups = (userinfo["groups"] && userinfo["wekanGroups"]) ? userinfo["wekanGroups"] : userinfo["groups"];
// groups arriving as array of strings indicate there is no scope set in oidc privider
// to assign teams and keep admin privileges
// data needs to be treated differently.
// use case: in oidc provider no scope is set, hence no group attributes.
// therefore: keep admin privileges for wekan as before
if(typeof serviceData.groups[0] === "string" )
{
user = Meteor.users.findOne({'_id': serviceData.id});
serviceData.groups.forEach(function(groupName, i)
{
if(user?.isAdmin && i == 0)
{
// keep information of user.isAdmin since in loginHandler the user will // be updated regarding group admin privileges provided via oidc
serviceData.groups[i] = {"isAdmin": true};
serviceData.groups[i]["displayName"]= groupName;
}
else
{
serviceData.groups[i] = {"displayName": groupName};
}
});
}
return {
serviceData: serviceData,
options: { profile: profile }
@ -208,6 +222,7 @@ if (process.env.ORACLE_OIM_ENABLED === 'true' || process.env.ORACLE_OIM_ENABLED
};
}
var getUserInfo = function (accessToken) {
var debug = process.env.DEBUG || false;
var config = getConfiguration();
@ -263,6 +278,28 @@ var getTokenContent = function (token) {
}
return content;
}
Meteor.methods({
'groupRoutineOnLogin': function(info, userId)
{
check(info, Object);
check(userId, String);
var propagateOidcData = process.env.PROPAGATE_OIDC_DATA || false;
if (propagateOidcData)
{
users= Meteor.users;
user = users.findOne({'_id': userId});
if(user)
{
//updates/creates Groups and user admin privileges accordingly
addGroupsWithAttributes(user, info.groups);
if(info.email) addEmail(user, info.email);
if(info.fullname) changeFullname(user, info.fullname);
if(info.username) changeUsername(user, info.username);
}
}
}
});
Oidc.retrieveCredential = function (credentialToken, credentialSecret) {
return OAuth.retrieveCredential(credentialToken, credentialSecret);