code.gitea.io/gitea@v1.22.3/services/auth/source/oauth2/store.go (about) 1 // Copyright 2021 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package oauth2 5 6 import ( 7 "encoding/gob" 8 "fmt" 9 "net/http" 10 11 "code.gitea.io/gitea/modules/log" 12 session_module "code.gitea.io/gitea/modules/session" 13 14 chiSession "gitea.com/go-chi/session" 15 "github.com/gorilla/sessions" 16 ) 17 18 // SessionsStore creates a gothic store from our session 19 type SessionsStore struct { 20 maxLength int64 21 } 22 23 // Get should return a cached session. 24 func (st *SessionsStore) Get(r *http.Request, name string) (*sessions.Session, error) { 25 return st.getOrNew(r, name, false) 26 } 27 28 // New should create and return a new session. 29 // 30 // Note that New should never return a nil session, even in the case of 31 // an error if using the Registry infrastructure to cache the session. 32 func (st *SessionsStore) New(r *http.Request, name string) (*sessions.Session, error) { 33 return st.getOrNew(r, name, true) 34 } 35 36 // getOrNew gets the session from the chi-session if it exists. Override permits the overriding of an unexpected object. 37 func (st *SessionsStore) getOrNew(r *http.Request, name string, override bool) (*sessions.Session, error) { 38 chiStore := chiSession.GetSession(r) 39 40 session := sessions.NewSession(st, name) 41 42 rawData := chiStore.Get(name) 43 if rawData != nil { 44 oldSession, ok := rawData.(*sessions.Session) 45 if ok { 46 session.ID = oldSession.ID 47 session.IsNew = oldSession.IsNew 48 session.Options = oldSession.Options 49 session.Values = oldSession.Values 50 51 return session, nil 52 } else if !override { 53 log.Error("Unexpected object in session at name: %s: %v", name, rawData) 54 return nil, fmt.Errorf("unexpected object in session at name: %s", name) 55 } 56 } 57 58 session.IsNew = override 59 session.ID = chiStore.ID() // Simply copy the session id from the chi store 60 61 return session, chiStore.Set(name, session) 62 } 63 64 // Save should persist session to the underlying store implementation. 65 func (st *SessionsStore) Save(r *http.Request, w http.ResponseWriter, session *sessions.Session) error { 66 chiStore := chiSession.GetSession(r) 67 68 if session.IsNew { 69 _, _ = session_module.RegenerateSession(w, r) 70 session.IsNew = false 71 } 72 73 if err := chiStore.Set(session.Name(), session); err != nil { 74 return err 75 } 76 77 if st.maxLength > 0 { 78 sizeWriter := &sizeWriter{} 79 80 _ = gob.NewEncoder(sizeWriter).Encode(session) 81 if sizeWriter.size > st.maxLength { 82 return fmt.Errorf("encode session: Data too long: %d > %d", sizeWriter.size, st.maxLength) 83 } 84 } 85 86 return chiStore.Release() 87 } 88 89 type sizeWriter struct { 90 size int64 91 } 92 93 func (s *sizeWriter) Write(data []byte) (int, error) { 94 s.size += int64(len(data)) 95 return len(data), nil 96 } 97 98 var _ (sessions.Store) = &SessionsStore{}