Skip to content

Commit

Permalink
fixes session cookie
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastianconcept committed Feb 23, 2024
1 parent 1b566c8 commit 9f21bfc
Show file tree
Hide file tree
Showing 4 changed files with 201 additions and 20 deletions.
23 changes: 20 additions & 3 deletions Ride-Builder/RideAppClassHelper.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,16 @@ RideAppClassHelper class >> newSessionWith_UrlMethodFor: aSymbol [
"Answer a new {1}App session with the given sessionId and url."
^ {1}Session newWith: sessionId url: anUrl
^ self sessionClass newWith: sessionId url: anUrl
' format: { aSymbol }
]

{ #category : #accessing }
RideAppClassHelper class >> sessionClassMethodFor: aSymbol [

^ 'sessionClass
^ {1}Session
' format: { aSymbol }
]

Expand Down Expand Up @@ -90,11 +99,18 @@ RideAppClassHelper >> addInstallMethodTo: aClass for: aSymbol [

{ #category : #actions }
RideAppClassHelper >> addNewSessionWith_UrlMethodTo: aClass for: aSymbol [

self deprecated: 'not used'.
aClass class compile: (self class newSessionWith_UrlMethodFor: aSymbol).
aClass class organization classify: #'newSessionWith:url:' under: 'actions'
]

{ #category : #actions }
RideAppClassHelper >> addSessionClassMethodTo: aClass for: aSymbol [

aClass class compile: (self class sessionClassMethodFor: aSymbol).
aClass class organization classify: #sessionClass under: 'accessing'
]

{ #category : #accessing }
RideAppClassHelper >> classNameFor: aSymbol [

Expand All @@ -114,7 +130,8 @@ RideAppClassHelper >> for: aSymbol [
| appClass |
appClass := super for: aSymbol.

self addNewSessionWith_UrlMethodTo: appClass for: aSymbol.
self addSessionClassMethodTo: appClass for: aSymbol.
"self addNewSessionWith_UrlMethodTo: appClass for: aSymbol."
self addInstallMethodTo: appClass for: aSymbol.
self addApplicationResourceClassMethodTo: appClass for: aSymbol.
self addInitializeServerMethodTo: appClass for: aSymbol.
Expand Down
20 changes: 18 additions & 2 deletions Ride/RidePresenter.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,15 @@ RidePresenter >> currentSession [
^ RideCurrentSession value
]

{ #category : #actions }
RidePresenter >> ensureSessionCookie [

| response sessionCookie |
response := RideCurrentResponse value.
sessionCookie := self currentSession sessionCookie.
response headers at: 'Set-Cookie' put: sessionCookie fullString
]

Check warning on line 245 in Ride/RidePresenter.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RidePresenter.class.st#L239-L245

Added lines #L239 - L245 were not covered by tests

{ #category : #actions }
RidePresenter >> formAction [
"Makes the receiver perform the action corresponding to a RESTful convention
Expand Down Expand Up @@ -397,7 +406,7 @@ RidePresenter >> newAuthToken [
{ #category : #actions }
RidePresenter >> onAboutToRespond [

"no-op is the default"
self ensureSessionCookie

Check warning on line 409 in Ride/RidePresenter.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RidePresenter.class.st#L409

Added line #L409 was not covered by tests
]

{ #category : #actions }
Expand Down Expand Up @@ -521,7 +530,7 @@ RidePresenter >> renderUsing: aSelector [
{ #category : #actions }
RidePresenter >> resetSession [

Ride service invalidateSession: self currentSession
Ride service invalidateSessionId: self currentSession

Check warning on line 533 in Ride/RidePresenter.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RidePresenter.class.st#L533

Added line #L533 was not covered by tests
]

{ #category : #accessing }
Expand Down Expand Up @@ -577,6 +586,13 @@ RidePresenter >> templateContext [
template ]
]

{ #category : #accessing }
RidePresenter >> unauthorizedHandler [
"Answers a handler to react when the auth token is missing or was not found."

^ [ RideUnauthorizedError signal: 'Authorization not found' ]
]

Check warning on line 594 in Ride/RidePresenter.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RidePresenter.class.st#L590-L594

Added lines #L590 - L594 were not covered by tests

{ #category : #actions }
RidePresenter >> updateModelFromRequest: aRequest [
"Updates the model data following the convention of expecting for all its data keys,
Expand Down
41 changes: 35 additions & 6 deletions Ride/RideService.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ RideService class >> applicationResourceClass [
{ #category : #accessing }
RideService class >> getSessionGetter [

^ [ :request |
^ [ :request |

Check warning on line 32 in Ride/RideService.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideService.class.st#L32

Added line #L32 was not covered by tests
| sessionId |
sessionId := self sessionIdFromCookieOrNewFrom: request.
Ride service sessions
at: sessionId
ifAbsentPut: [ self newSessionWith: sessionId url: request url ] ]
ifAbsentPut: [ self newSessionWith: sessionId request: request ] ]

Check warning on line 37 in Ride/RideService.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideService.class.st#L37

Added line #L37 was not covered by tests
]

{ #category : #accessing }
Expand All @@ -61,9 +61,11 @@ RideService class >> log: aString level: aSymbol [
RideService class >> newResetSessionCookie [

| expires cookieString domain |
self deprecated: 'using this from the session'.

Check warning on line 64 in Ride/RideService.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideService.class.st#L64

Added line #L64 was not covered by tests
domain := Ride service server router domain.
expires := ZnUtils httpDate: DateAndTime now - 10 years.
cookieString := 'id={1}; expires={2}; path=/; domain={3}' format: {
cookieString := '{1}={2}; expires={3}; path=/; domain={4}' format: {
Ride service sessionClass cookieName.

Check warning on line 68 in Ride/RideService.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideService.class.st#L67-L68

Added lines #L67 - L68 were not covered by tests
String new.
expires.
domain }.
Expand All @@ -76,9 +78,15 @@ RideService class >> newSessionId [
^ UUID new asString36
]

{ #category : #actions }
RideService class >> newSessionWith: sessionId request: aRequest [

^ self sessionClass newWith: sessionId request: aRequest
]

Check warning on line 85 in Ride/RideService.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideService.class.st#L82-L85

Added lines #L82 - L85 were not covered by tests

{ #category : #accessing }
RideService class >> newSessionWith: sessionId url: anUrl [

self deprecated: 'not used'.

Check warning on line 89 in Ride/RideService.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideService.class.st#L89

Added line #L89 was not covered by tests
self subclassResponsibility
]

Expand All @@ -98,13 +106,21 @@ RideService class >> restart [
]

{ #category : #accessing }
RideService class >> sessionIdFromCookieOrNewFrom: aRequest [
RideService class >> sessionClass [

^ self subclassResponsibility
]

{ #category : #accessing }
RideService class >> sessionIdFromCookieOrNewFrom: aRequest [

Check warning on line 115 in Ride/RideService.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideService.class.st#L115

Added line #L115 was not covered by tests
"Answers the session ID taken from the cookie of the given aRequest.
Answers a new one if the cookie is absent "

| cookieName |
cookieName := Ride service sessionClass cookieName.

Check warning on line 121 in Ride/RideService.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideService.class.st#L119-L121

Added lines #L119 - L121 were not covered by tests
^ (aRequest cookies
detect: [ :each | each name = 'id' ]
detect: [ :each | each name = cookieName ]

Check warning on line 123 in Ride/RideService.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideService.class.st#L123

Added line #L123 was not covered by tests
ifNone: [ ^ self newSessionId ]) value
]

Expand Down Expand Up @@ -240,6 +256,13 @@ RideService >> invalidateSession: aRideSession [
put: Ride service class newResetSessionCookie fullString
]

{ #category : #actions }
RideService >> invalidateSessionId: aRideSessionId [
"Remove the given session from the cache"

sessions removeKey: aRideSessionId ifAbsent: [ ]
]

Check warning on line 264 in Ride/RideService.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideService.class.st#L260-L264

Added lines #L260 - L264 were not covered by tests

{ #category : #accessing }
RideService >> locator [
self deprecated: 'use Ride resource instead'.
Expand Down Expand Up @@ -371,6 +394,12 @@ RideService >> server: anObject [
server := anObject
]

{ #category : #accessing }
RideService >> sessionClass [

^ self class sessionClass
]

Check warning on line 401 in Ride/RideService.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideService.class.st#L398-L401

Added lines #L398 - L401 were not covered by tests

{ #category : #accessing }
RideService >> sessionGetter [

Expand Down
137 changes: 128 additions & 9 deletions Ride/RideSession.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,88 @@ Class {
'id',
'webSocket',
'cache',
'values'
'values',
'authenticityTokens',
'cookie'
],
#classInstVars : [
'authenticityTokenGenerator'
],
#category : #'Ride-Core'
}

{ #category : #accessing }
RideSession class >> authenticityTokenGenerator [

^ authenticityTokenGenerator := UUIDGenerator new
]

Check warning on line 26 in Ride/RideSession.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideSession.class.st#L23-L26

Added lines #L23 - L26 were not covered by tests

{ #category : #actions }
RideSession class >> cookieName [
"Answers the session cookie name."

^ self name asString
]

Check warning on line 33 in Ride/RideSession.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideSession.class.st#L29-L33

Added lines #L29 - L33 were not covered by tests

{ #category : #actions }
RideSession class >> newSessionCookieId: anId expiring: aDateAndTime [

| domain expires cookieString |
domain := Ride service server router domain.
expires := ZnUtils httpDate: aDateAndTime.
cookieString := '{1}={2}; expires={3}; path=/; domain={4}' format: {
Ride service sessionClass cookieName.
anId.
expires.
domain }.

^ ZnCookie fromString: cookieString for: ('http://' , domain) asZnUrl
]

Check warning on line 48 in Ride/RideSession.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideSession.class.st#L36-L48

Added lines #L36 - L48 were not covered by tests

{ #category : #'instance creation' }
RideSession class >> newWith: anId url: anUrl [
RideSession class >> newWith: anId request: aRequest [

^ self new initializeWith: anId request: aRequest
]

Check warning on line 54 in Ride/RideSession.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideSession.class.st#L51-L54

Added lines #L51 - L54 were not covered by tests

{ #category : #'instance creation' }
RideSession class >> newWith: anId url: anUrl [
self deprecated: 'not used'.

Check warning on line 58 in Ride/RideSession.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideSession.class.st#L57-L58

Added lines #L57 - L58 were not covered by tests
^ self new initializeWith: anId url: anUrl
]

{ #category : #actions }
RideSession >> add: routeKey presenter: aRidePresenter [
RideSession class >> nextAuthenticityTokenValue [

^ self authenticityTokenGenerator next asString36
]

Check warning on line 66 in Ride/RideSession.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideSession.class.st#L63-L66

Added lines #L63 - L66 were not covered by tests

{ #category : #actions }
RideSession class >> reset [

Check warning on line 69 in Ride/RideSession.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideSession.class.st#L69

Added line #L69 was not covered by tests

authenticityTokenGenerator := nil
]

Check warning on line 72 in Ride/RideSession.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideSession.class.st#L71-L72

Added lines #L71 - L72 were not covered by tests

{ #category : #accessing }
RideSession class >> sessionDuration [

^ (Smalltalk os environment
at: #SESSION_DURATION
ifAbsent: [ 20 years asSeconds ]) asInteger seconds
]

Check warning on line 80 in Ride/RideSession.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideSession.class.st#L75-L80

Added lines #L75 - L80 were not covered by tests

{ #category : #actions }
RideSession >> add: routeKey presenter: aRidePresenter [
self deprecated: ' not used'.

Check warning on line 84 in Ride/RideSession.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideSession.class.st#L83-L84

Added lines #L83 - L84 were not covered by tests
^ self presenters at: routeKey put: aRidePresenter
]

{ #category : #accessing }
RideSession >> authenticityTokens [

^ authenticityTokens ifNil: [ self initializeAuthenticityTokens ]
]

Check warning on line 92 in Ride/RideSession.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideSession.class.st#L89-L92

Added lines #L89 - L92 were not covered by tests

{ #category : #accessing }
RideSession >> cache [

Expand Down Expand Up @@ -83,36 +148,79 @@ RideSession >> initialUrl: anUrl [
self values at: #initialUrl put: anUrl ]
]

{ #category : #initialization }
RideSession >> initializeAuthenticityTokens [

^ authenticityTokens := TTLCache new
]

Check warning on line 155 in Ride/RideSession.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideSession.class.st#L152-L155

Added lines #L152 - L155 were not covered by tests

{ #category : #initialization }
RideSession >> initializeCache [

^ cache := TTLCache new
]

{ #category : #initialization }
RideSession >> initializeCookieUsing: aRequest [

| newCookie |

newCookie := [
self class
newSessionCookieId:
self class nextAuthenticityTokenValue
expiring: DateAndTime now + self class sessionDuration ].

^ cookie := aRequest cookies
detect: [ :e | e name = self class cookieName ]
ifNone: [ newCookie value ]
]

Check warning on line 177 in Ride/RideSession.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideSession.class.st#L164-L177

Added lines #L164 - L177 were not covered by tests

{ #category : #initialization }
RideSession >> initializeValues [

^ values := SmallDictionary new
]

{ #category : #initialization }
RideSession >> initializeWith: anId url: anUrl [
RideSession >> initializeWith: anId request: aRequest [

Check warning on line 186 in Ride/RideSession.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideSession.class.st#L186

Added line #L186 was not covered by tests

super initialize.

id := anId.
self initializeCookieUsing: aRequest.

Check warning on line 191 in Ride/RideSession.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideSession.class.st#L191

Added line #L191 was not covered by tests
self initializeCache.
self initializeAuthenticityTokens.
self initialUrl: aRequest url
]

Check warning on line 195 in Ride/RideSession.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideSession.class.st#L193-L195

Added lines #L193 - L195 were not covered by tests

{ #category : #initialization }
RideSession >> initializeWith: anId url: anUrl [
self deprecated: 'not in use'.
super initialize.

id := anId.
self initializeCookie.
self initializeCache.
self initializeAuthenticityTokens.

Check warning on line 205 in Ride/RideSession.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideSession.class.st#L198-L205

Added lines #L198 - L205 were not covered by tests
self initialUrl: anUrl
]

{ #category : #actions }
RideSession >> invalidateAndRedirectTo: url [

| response |
Ride service invalidateSession: self.
Ride service invalidateSessionId: self id.

Check warning on line 213 in Ride/RideSession.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideSession.class.st#L213

Added line #L213 was not covered by tests
response := RideCurrentResponse value.

"Redirect"
"Reset the session cookie"
response headers
at: 'Set-Cookie'
put:
(self class newSessionCookieExpiring: DateAndTime now - 10 years)
fullString.

"and redirect"

Check warning on line 223 in Ride/RideSession.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideSession.class.st#L216-L223

Added lines #L216 - L223 were not covered by tests
response
code: 302;
location: url.
Expand All @@ -121,9 +229,14 @@ RideSession >> invalidateAndRedirectTo: url [

{ #category : #actions }
RideSession >> newAuthToken [
"Adds a new auth token"

^ cache at: #authenticity_token put: self newUUIDAsString36
"Adds a new auth token.
The authenticity tokens are stored by value with its own TTL
so request can be considered unauthorized when a request doesn't
include an existing one for this session."

| value |
value := self class nextAuthenticityTokenValue.
^ authenticityTokens at: value ifAbsentPut: [ value ]

Check warning on line 239 in Ride/RideSession.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideSession.class.st#L232-L239

Added lines #L232 - L239 were not covered by tests
]

{ #category : #actions }
Expand All @@ -144,6 +257,12 @@ RideSession >> remove: routeKey [
^ self presenters removeKey: routeKey ifAbsent: [ nil ]
]

{ #category : #accessing }
RideSession >> sessionCookie [

^ cookie
]

Check warning on line 264 in Ride/RideSession.class.st

View check run for this annotation

Codecov / codecov/patch

Ride/RideSession.class.st#L261-L264

Added lines #L261 - L264 were not covered by tests

{ #category : #accessing }
RideSession >> values [

Expand Down

0 comments on commit 9f21bfc

Please sign in to comment.