2014-03-29 81 views
0

我在基於用戶角色驗證和重新設置某些字段時遇到問題。 我想用grails開發一個rest api,當我嘗試根據用戶的角色重置一些字段時出現問題。我通過PUT向控制器發送帶有所需的「不允許」更改的json。我將不允許的字段修改爲對我來說不正確的字段,然後調用.save(),並且「未顯示」字段將使用它們的發送值進行更新,而不是使用修改後的值進行更新。這是代碼。Grails在保存前更新模型

THE MODEL

package phonebook 

class User { 
String firstName 
String lastName 
String phoneNo 
String address 
String email 
String password 
boolean active = false 
String hash 
String authToken = "" 
String role = "user" 

static hasMany = [contacts:Contact] 

static constraints = { 
    firstName(blank: false) 
    lastName(blank: false) 
    address(blank: true) 
    phoneNo(unique: true) 
    email(blank: false, unique: true) 
    password(blank: false) 
    role(blank: false, inList: ["user", "admin"]) 
    hash(blank: true) 
    authToken(blank: true) 
    active(inList:[true,false]) 
} 
} 

來自控制器的方法:

@Transactional 
def update(User userInstance) { 
    if (!isAuthenticated()){ 
     notAllowed() 
     return 
    } 

    if (userInstance == null) { 
     notFound() 
     return 
    } 

    //if(isAdmin()){ 
     def userBackup = User.findById(userInstance.id) 

     userInstance.role = userBackup.role 
     userInstance.active = userBackup.active 
     userInstance.hash = userBackup.hash 
     userInstance.authToken = userBackup.authToken 
    //} 

    if (userInstance.hasErrors()) { 
     respond userInstance.errors, view:'edit' 
     return 
    } 

    userInstance.save flush:false 

    request.withFormat { 
     '*'{ respond userInstance, [status: OK] } 
    } 
} 

THE JSON SENT VIA PUT

{ 
"id":"1", 
"firstName": "Modified Name 23", 
"role":"admin", 
"active":"true", 
"hash":"asdasd" 
} 

上面的代碼不應該修改我的散列或活性或值即使他們被髮送也是如此。

任何想法? 謝謝。

+0

你是什麼意思的「不允許」?你的意思是隻有特定的用戶才能修改這些字段 - 問題在於其他用戶似乎也能夠修改這些字段? – Denise

+0

。問題是,即使強硬我抵消了變化,它仍然更新與「不允許」值發送 –

回答

3

更改被保存的原因是因爲默認情況下,對域實例所做的任何更改都將在會話結束時刷新。這被稱爲打開會話,以及自動會話刷新。我建議你對人們在GORM中遇到的一些主要問題做some reading

正確使用discard可能會解決您的問題。在退出控制器之前放棄實例更改。

例如:

if (!isAuthenticated()){ 
    notAllowed() 
    userInstance.discard() 
    return 
} 

編輯

基礎上的對話在評論這也許可能是解決您的問題的方式。丟棄和附加的組合。

userInstance.discard() 
    def userBackup = User.findById(userInstance.id) 

    userInstance.role = userBackup.role 
    userInstance.active = userBackup.active 
    userInstance.hash = userBackup.hash 
    userInstance.authToken = userBackup.authToken 
    userInstance.attach() 
+0

問題出現在用戶備份,Hibernate的beaqcuse,userBackup(取自數據庫)和userInstance(取作參數)是同樣沒有調用保存:( –

+0

這是因爲當你加載userBackup時,它看到實例已經存在於Hibernate緩存中,這是你已經加載並修改的實例,如果你打開SQL日誌記錄,你會發現它實際上並沒有再次調用數據庫來加載該記錄。 –

0

我被這種方法所幫助。

getPersistentValue

def update(ShopItem shopItemInstance) { 

    if (shopItemInstance == null) { 
     notFound() 
     return 
    } 

    if (!shopItemInstance.itemPhoto){ 
     shopItemInstance.itemPhoto = 
       shopItemInstance.getPersistentValue("itemPhoto"); 
    } 

    if (shopItemInstance.hasErrors()) { 
     respond shopItemInstance.errors, view:'edit' 
     return 
    } 


    shopItemInstance.save flush:true 
    redirect(action: "show", id: shopItemInstance.id) 
} 

你的情況:

userInstance.role = userInstance.getPersistentValue("role") 
    userInstance.active = userInstance.getPersistentValue("active") 
    userInstance.hash = userInstance.getPersistentValue("hash") 
    userInstance.authToken = userInstance.getPersistentValue("authToken") 
0

它的更好,如果你使用的命令對象功能。您可以將命令對象綁定到請求負載,驗證它並找到並更新域對象。

你可以在這裏找到更多的細節: http://grails.org/doc/2.3.x/guide/theWebLayer.html#commandObjects

和關閉記錄你shoudn't在你的控制器使用@Transactional。您可以將該代碼移動到服務中。

當量:

DEF更新(長ID,UserCommand CMD){// Grails將映射JSON對象到命令對象,並將調用validate()方法,如果類與@Validatable

註釋

}

相關問題