engineercms分享文件提取碼-參考藍眼雲盤

因為藍眼雲盤也是採用go語言+gorm編寫的,所以參考起來稍微輕鬆一點。主要還是了解如何通過一段提取碼就能取到文件的訪問權。

生成一個分享文件uuid和提取碼code。服務端接受選擇的文件或文件夾id,隨機生成一個share uuid和提取碼code,返回給頁面:服務端寫入數據表share和bridge,前者存share uuid和分享者id,及過期時間expiretime,還有是否永久有效。後者存儲share uuid和對應的文件id,一對多。

用戶通過這個鏈接地址,瀏覽器請求服務端,服務端判斷用戶有無登錄——如果登錄,再判斷這個分享是不是這個登錄用戶創建。如果沒登錄,則需要提取碼code。

當輸入code後,服務根據share uuid,和code,通過讀取share數據表,如果符合,則根據share uuid取出bridge里的文件列表

當用戶全部打包下載,或下載其中一個,怎麼處理邏輯呢?再通過share uuid和code做一次判斷么?

// check whether shareUuid and shareCode matches. check whether user can access.  func (this *ShareService) CheckShare(request *http.Request, shareUuid string, code string, user *User) *Share {    	share := this.shareDao.CheckByUuid(shareUuid)  	//if self, not need shareCode  	if user == nil || user.Uuid != share.UserUuid {  		//if not login or not self's share, shareCode is required.  		if code == "" {  			panic(result.CustomWebResultI18n(request, result.NEED_SHARE_CODE, i18n.ShareCodeRequired))  		} else if share.Code != code {  			panic(result.CustomWebResultI18n(request, result.SHARE_CODE_ERROR, i18n.ShareCodeError))  		} else {  			if !share.ExpireInfinity {  				if share.ExpireTime.Before(time.Now()) {  					panic(result.BadRequest("share expired"))  				}  			}  		}  	}  	return share  }

如果是自己,就不需要提取碼,不是自己的,或者沒有登錄,就判斷提取碼,如果有提取碼,就和資料庫中存的對比,如果正確,再判斷有效期,如果是永遠的,則不需要判斷過期時間。如果不是永遠有效的,則看看資料庫里的過期時間跟當前時間對比。

上面的邏輯相當於通過認證後,提供給頁面的文件或文件列表。

那麼下載也差不多是這個邏輯,也是要判斷code。

func (this *ShareController) Zip(writer http.ResponseWriter, request *http.Request) *result.WebResult {    	shareUuid := request.FormValue("shareUuid")  	code := request.FormValue("code")    	puuid := request.FormValue("puuid")  	rootUuid := request.FormValue("rootUuid")    	user := this.findUser(request)    	if puuid == MATTER_ROOT {    		//download all things.  		share := this.shareService.CheckShare(request, shareUuid, code, user)  		bridges := this.bridgeDao.FindByShareUuid(share.Uuid)  		var matterUuids []string  		for _, bridge := range bridges {  			matterUuids = append(matterUuids, bridge.MatterUuid)  		}  		matters := this.matterDao.FindByUuids(matterUuids, nil)  		this.matterService.DownloadZip(writer, request, matters)    	} else {    		//download a folder.  		matter := this.matterDao.CheckByUuid(puuid)  		this.shareService.ValidateMatter(request, shareUuid, code, user, rootUuid, matter)  		this.matterService.DownloadZip(writer, request, []*Matter{matter})  	}    	return nil  }

也是先要checkshare,然後再去bridge數據表裡取出文件或文件的id……如果是文件夾,則用validatematter判斷,也是一樣的:

//check whether a user can access a matter. shareRootUuid is matter's parent(or parent's parent and so on)  func (this *ShareService) ValidateMatter(request *http.Request, shareUuid string, code string, user *User, shareRootUuid string, matter *Matter) {    	if matter == nil {  		panic(result.Unauthorized("matter cannot be nil"))  	}    	//if self's matter, ok.  	if user != nil && matter.UserUuid == user.Uuid {  		return  	}    	if shareUuid == "" || code == "" || shareRootUuid == "" {  		panic(result.Unauthorized("shareUuid,code,shareRootUuid cannot be null"))  	}    	share := this.CheckShare(request, shareUuid, code, user)    	//if shareRootUuid is root. Bridge must has record.  	if shareRootUuid == MATTER_ROOT {    		this.bridgeDao.CheckByShareUuidAndMatterUuid(share.Uuid, matter.Uuid)    	} else {  		//check whether shareRootMatter is being sharing  		shareRootMatter := this.matterDao.CheckByUuid(shareRootUuid)  		this.bridgeDao.CheckByShareUuidAndMatterUuid(share.Uuid, shareRootMatter.Uuid)    		// shareRootMatter is ancestor of matter.  		child := strings.HasPrefix(matter.Path, shareRootMatter.Path)  		if !child {  			panic(result.BadRequest("%s is not %s's children", matter.Uuid, shareRootUuid))  		}  	}    }

也是要checkshare一下的。

Tags: