github.com/uvalib/orcid-access-ws@v0.0.0-20250612130209-7d062dbabf9d/orcidaccessws/handlers/update_activity_handler.go (about) 1 package handlers 2 3 import ( 4 "encoding/json" 5 "errors" 6 "fmt" 7 "github.com/gorilla/mux" 8 "github.com/uvalib/orcid-access-ws/orcidaccessws/api" 9 "github.com/uvalib/orcid-access-ws/orcidaccessws/authtoken" 10 "github.com/uvalib/orcid-access-ws/orcidaccessws/config" 11 "github.com/uvalib/orcid-access-ws/orcidaccessws/dao" 12 "github.com/uvalib/orcid-access-ws/orcidaccessws/logger" 13 "github.com/uvalib/orcid-access-ws/orcidaccessws/orcid" 14 "io" 15 "io/ioutil" 16 "net/http" 17 ) 18 19 var emptyUpdateCode = "" 20 21 // UpdateActivity -- update activity handler 22 func UpdateActivity(w http.ResponseWriter, r *http.Request) { 23 24 vars := mux.Vars(r) 25 id := vars["id"] 26 token := r.URL.Query().Get("auth") 27 28 // parameters OK? 29 if isEmpty(id) || isEmpty(token) { 30 status := http.StatusBadRequest 31 encodeUpdateActivityResponse(w, status, http.StatusText(status), emptyUpdateCode) 32 return 33 } 34 35 // validate the token 36 if authtoken.Validate(config.Configuration.SharedSecret, token) == false { 37 status := http.StatusForbidden 38 encodeUpdateActivityResponse(w, status, http.StatusText(status), emptyUpdateCode) 39 return 40 } 41 42 decoder := json.NewDecoder(r.Body) 43 activity := api.ActivityUpdate{} 44 45 if err := decoder.Decode(&activity); err != nil { 46 logger.Log(fmt.Sprintf("ERROR: decoding update activity request payload: %s", err)) 47 status := http.StatusBadRequest 48 encodeUpdateActivityResponse(w, status, 49 fmt.Sprintf("%s (%s)", http.StatusText(status), err.Error()), 50 emptyUpdateCode) 51 return 52 } 53 54 defer io.Copy(ioutil.Discard, r.Body) 55 defer r.Body.Close() 56 57 if err := validateRequestPayload(activity); err != nil { 58 logger.Log(fmt.Sprintf("ERROR: invalid request payload: %s", err)) 59 status := http.StatusBadRequest 60 encodeUpdateActivityResponse(w, status, 61 fmt.Sprintf("%s (%s)", http.StatusText(status), err.Error()), 62 emptyUpdateCode) 63 return 64 } 65 66 // get the users ORCID attributes 67 attributes, err := dao.Store.GetOrcidAttributesByCid(id) 68 if err != nil { 69 logger.Log(fmt.Sprintf("ERROR: %s", err.Error())) 70 status := http.StatusInternalServerError 71 encodeUpdateActivityResponse(w, status, 72 fmt.Sprintf("%s (%s)", http.StatusText(status), err.Error()), 73 emptyUpdateCode) 74 return 75 } 76 77 // we did not find the item, return 404 78 if attributes == nil || len(attributes) == 0 { 79 status := http.StatusNotFound 80 encodeUpdateActivityResponse(w, status, http.StatusText(status), emptyUpdateCode) 81 return 82 } 83 84 // verify the attributes are sufficient for our needs 85 if err := validateOrcidAttributes(*attributes[0]); err != nil { 86 logger.Log(fmt.Sprintf("ERROR: invalid ORCID attributes for cid %s: %s", id, err)) 87 status := http.StatusBadRequest 88 encodeUpdateActivityResponse(w, status, 89 fmt.Sprintf("%s (%s)", http.StatusText(status), err.Error()), 90 emptyUpdateCode) 91 return 92 } 93 94 // update the activity 95 updateCode, status, err := orcid.UpdateOrcidActivity(attributes[0].Orcid, attributes[0].OauthAccessToken, activity) 96 97 // the token might be expired, lets try to renew it 98 if false { //status == http.StatusUnauthorized { 99 var newAccessToken = "" 100 var newRefreshToken = "" 101 // renew the access token... 102 newAccessToken, newRefreshToken, status, err = orcid.RenewAccessToken(attributes[0].OauthRefreshToken) 103 if status == http.StatusOK { 104 attributes[0].OauthAccessToken = newAccessToken 105 attributes[0].OauthRefreshToken = newRefreshToken 106 // save the new tokens 107 err = dao.Store.SetOrcidAttributesByCid(id, *attributes[0]) 108 109 // if successful, retry the activity update 110 if err == nil { 111 updateCode, status, err = orcid.UpdateOrcidActivity(attributes[0].Orcid, attributes[0].OauthAccessToken, activity) 112 } else { 113 logger.Log(fmt.Sprintf("ERROR: %s", err.Error())) 114 status = http.StatusInternalServerError 115 } 116 } 117 } 118 119 // we did got an error, return it 120 if status != http.StatusOK { 121 encodeUpdateActivityResponse(w, status, 122 fmt.Sprintf("%s (%s)", http.StatusText(status), err), emptyUpdateCode) 123 return 124 } 125 126 encodeUpdateActivityResponse(w, status, http.StatusText(status), updateCode) 127 } 128 129 // basic validation that the required fields for the activity update request exist 130 func validateRequestPayload(activity api.ActivityUpdate) error { 131 132 if len(activity.Work.Title) == 0 { 133 return errors.New("empty work title") 134 } 135 136 if len(activity.Work.ResourceType) == 0 { 137 return errors.New("empty work resource type") 138 } 139 140 if len(activity.Work.URL) == 0 { 141 return errors.New("empty work url") 142 } 143 144 return nil 145 } 146 147 // validation that the necessary ORCID attributes exist before we use them 148 func validateOrcidAttributes(attributes api.OrcidAttributes) error { 149 150 if len(attributes.Orcid) == 0 { 151 return errors.New("blank ORCID attribute") 152 } 153 154 if len(attributes.OauthAccessToken) == 0 { 155 return errors.New("blank OAuth access token") 156 } 157 158 if len(attributes.OauthRefreshToken) == 0 { 159 return errors.New("blank OAuth refresh token") 160 } 161 162 return nil 163 } 164 165 // 166 // end of file 167 //