2014-03-26 226 views
12

我正嘗試使用Atmosphere中的'角色'包,但無法使用Accounts.onCreateUser(),我可以獲得在github上的例子。當我註冊一個用戶時,我想向他們添加一個角色,當我測試角色是否被分配時,它不會選擇它。無法使用「角色」包向流星添加角色

這裏是我的代碼

/server/users.js

Accounts.onCreateUser(function(options, user){ 
    var role = ['admin']; 
    Roles.addUsersToRoles(user, role); 
    return user; 
}); 

/client/page.js

Template.hello.events({ 
    'click input': function() { 
    var loggedInUser = Meteor.user(); 
    if (Roles.userIsInRole(loggedInUser, ['admin'])) { 
     console.log("Hi Admin!"); 
    }else{ 
     console.log("Please Log In"); 
    } 
    } 
}); 

回答

12

如果你在看代碼的Roles包正在使用你將看到他們使用您傳入的user/userId在用戶的集合上執行查詢(here,從行〜623開始):

(:返回的文檔直接插入收集Meteor.users docs),當它執行查詢Roles找不到它
try { 
    if (Meteor.isClient) { 
    // On client, iterate over each user to fulfill Meteor's 
    // 'one update per ID' policy 
    _.each(users, function (user) { 
     Meteor.users.update({_id: user}, update) 
    }) 
    } else { 
    // On the server we can use MongoDB's $in operator for 
    // better performance 
    Meteor.users.update(
     {_id: {$in: users}}, 
     update, 
     {multi: true}) 
    } 
} 

由於onCreateUser用戶對象被插入到收集之前被調用。

爲了解決這個問題,您必須等到用戶插入到集合中。如果你看看Roles包,他們的所有例子都顯示了這一點。像here,(第二個例子中,添加註釋),與許多人一起:

// insert user and retrieve the id 
id = Accounts.createUser({ 
    email: user.email, 
    password: "apple1", 
    profile: { name: user.name } 
}); 

// now we can verify that the user was inserted and add permissions 
if (user.roles.length > 0) { 
    Roles.addUsersToRoles(id, user.roles); 
} 

。希望照在你的問題的一些情況。所以基本上只需插入用戶,然後添加權限。

+0

優秀的答案。我以前見過這個問題,並願意接受建議。也許只是在文檔中特別提到這一點? – alanning

+0

@alanning謝謝!是的,這可能會引起一些混亂。我個人建議在文檔中添加一些內容。即使只是在氣氛頁面上的* client *部分之後添加備註,也可能會捕獲這些情況中的一部分。否則,希望人們會開始找到與其相關的SO帖子。 – Firo

+0

更新的文檔:https://atmosphere.meteor.com/package/roles – alanning

5

我不明白如何將Roles.addUsersToRoles與創建用戶時調用的onCreateUser函數進行集成。正如你所做的那樣,它在OnCreateUser中被調用時不起作用,就像你找到的那樣。但是在用戶創建循環中調用addUsersToRoles的示例大多不適用於創建帳戶的新用戶的正常用例。

相反,我只是做:

Accounts.onCreateUser(function(options, user){ 
    var role = ['admin']; 
    user.roles = role 
    return user; 
}); 
+1

雖然這適用於角色,但如果您同時擁有角色和組,則不起作用。通常情況下,你會得到這樣的:' 「角色」:{ \t \t 「__global_roles__」: \t \t \t 「管理員」 \t \t] \t}, ' – d4nyll

+0

將這項工作,如果''admin''還沒有在角色集合中?這會將它添加到角色集合嗎? – Dan

9

要的東西添加到用戶的文檔已經插入由accounts包後,嘗試這種模式。請注意,您必須輸入meteor add random才能生成userId,在此情況下這是安全的。

Accounts.onCreateUser(function (options, user) { 
    // Semantics for adding things to users after the user document has been inserted 
    var userId = user._id = Random.id(); 
    var handle = Meteor.users.find({_id: userId}, {fields: {_id: 1}}).observe({ 
     added: function() { 
      Roles.addUsersToRoles(userId, ['admin']); 
      handle.stop(); 
      handle = null; 
     } 
    }); 

    // In case the document is never inserted 
    Meteor.setTimeout(function() { 
     if (handle) { 
      handle.stop(); 
     } 
    }, 30000); 

    return user; 
}); 
+0

這比'user.roles = ['admin']'還好,比如dojomouse的答案是什麼? – Dan

+1

@dojomouse的答案對「allaning:roles」的工作原理做了假設。如果他們不將角色存儲在一個字符串數組中,會怎麼樣?如果其他一些代碼修改角色呢?如果你更新'roles'並且增加了一種方法來做到這一點呢?在對dojomouse解決方案的評論中,你實際上似乎是一個例子,如果你直接修改這個數組,你會100%破壞一些東西。這樣,你可以保證只要'addUsersToRoles'不會改變,你就不會去別的東西。 – DoctorPangloss

+0

這比Joe的答案要複雜得多,它不需要手動設置用戶ID,添加另一個不必要的依賴關係,或者儘可能多的代碼行,儘管它爲可能需要的更復雜的功能提供了一個整齊的觀察者模式onCreateUser。 –

5

接受的答案迫使你寫通過賬戶的UI /密碼,由流星給出登錄邏輯樣板代碼。 其他答案對基礎實現做出了假設,超時解決方案引入了競爭條件。

爲什麼不能做到這一點:

Accounts.onCreateUser(function(options, user) { 
 

 
    ... 
 

 
    Meteor.setTimeout(function() { 
 
     Roles.addUsersToRoles(user._id, roles, group); 
 
    },0); 
 
    ... 
 
    
 
});

您有效地添加的角色後,不管它是什麼觸發了onCreateUser通話,並使用alanning的API添加到角色。 (用流星1.0測試,角色1.2。13)

+0

這裏使用setTimeout()函數的相關性是什麼? – jlouzado

+1

在onCreateUser的時候,用戶還沒有真正創建過。由於javascript是一個單線程的進程,因此'Meteor.setTimeout'保證內部函數在用戶創建的當前線程之後被調用*。 – Joe

+1

我覺得'Meteor.defer()'比'setTimeout'和'0'有一些優勢,但我不能100%確定它的優點。 :) – chmac

1

我不想重寫Meteor的帳戶包提供的邏輯,自己設置ID,或者使用setTimeout。

相反,我有跟蹤代碼看着Meteor.user()調用,它返回用戶如果登錄,如果不是,則返回null。

因此,有效的是,一旦用戶登錄,此代碼將檢查是否已分配角色,以及是否未添加角色。

我確實必須使用Meteor方法,因爲我不想讓角色與客戶端混淆,但是您可以更改它。

/* client */ 
Tracker.autorun(function() { 
    var user = Meteor.user(); 
    if (user && !Roles.getRolesForUser(user).length) { 
    Meteor.call('addUserRole', user); 
    } 
}); 

/* server */ 
Meteor.methods({ 
    addUserRole: function (user) { 
    Roles.addUsersToRoles(user, user.profile.edmodo.type); 
    }, 
}); 
0

我的方式我發現要做到這一點,這很簡單。

我傳遞作用的陣列,所以就用[作用]

在客戶端中,當用戶註冊:

var role = $(event.target).find('#role').val(); 

/* 
* Add account - Client-Side 
*/ 
Accounts.createUser(account, (error) => { 
    if (error) { 
    console.log(error); 
    } else { 
    // server-side call to add the user to the role 
    // notice Meteor.userId() and [role] 
    Meteor.call('assignUserToRole', Meteor.userId(), [role]); 

    // everything went well, redirect to home 
    FlowRouter.go('home'); 
    } 
}); 

在我們的流星的方法(我使用lodash相交方法來驗證我希望用戶選擇的角色)

Meteor.methods({ 
    // when a account is created make sure we limit the roles 
    assignUserToRole: (userId, roles) => { 
     check(userId, String); 
     check(roles, Array); 

     var allowedRoles = ['student', 'parent', 'teacher']; 
     if (_.intersection(allowedRoles, roles).length > 0) { 
     Roles.addUsersToRoles(userId, roles, 'user'); 
     } else { 
     Roles.addUsersToRoles(userId, ['student'], 'user'); 
     } 
    } 
    }); 
2

這裏的問題其實就是要尋找一個創建用戶掛機(其中onCreateUser不是)。

事實證明,這樣的事情存在!它被稱爲postSignUpHook

https://github.com/meteor-useraccounts/core/blob/master/Guide.md#options

我發現這個從這個蘇答案:

https://stackoverflow.com/a/34114000/3221576

這是添加角色與樣板UserAccounts包創建的用戶(即,如果你不是首選方法用Accounts.createUser滾動你自己)。

UPDATE

最後,我結束了使用matb33:收集鉤按本評論:

https://github.com/alanning/meteor-roles/issues/35#issuecomment-198979601

只要堅持這些代碼在你的Meteor.startup和工作的事情如預期。

+0

這就是我正在尋找的解決方案! – kroe