Skip to content

Commit bfb2ebf

Browse files
authored
Release v3.0.8 (#121)
* [iOS] Adds type’s default ordering to search results. * [CoreSummit] Sets inital data load date to summit payload timestamp. * [CoreSummit] [14427] Data wipes when data update age is older than a week. -Fetches logged member data when fetching new summit. -Clears data update poller session after data wipe. * [CoreSummit] [14427] Clears session tokens on logout. * [CoreSummit] [14427] Sets polling interval to 30 seconds. * [CoreSummit] [14427] Adds refresh data button in about section. * [iOS] [14427] Fixes speakers section bug on data wipe. * [iOS] [14406] Fixes map zooming. * [iOS] Adds background to search results cell header. * Version bump to 3.0.8
1 parent 370eb7d commit bfb2ebf

18 files changed

Lines changed: 267 additions & 116 deletions

OpenStack Summit/CoreSummit/DataUpdate.swift

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -107,46 +107,56 @@ public extension DataUpdate {
107107

108108
public extension Store {
109109

110+
enum DataUpdateProcessResult {
111+
112+
case dataWipe
113+
case success(Bool)
114+
}
115+
110116
/// Processes the data update, but does not save the context.
111-
func process(dataUpdate: DataUpdate, summit: Identifier) -> Bool {
117+
func process(dataUpdate: DataUpdate, summit: Identifier) -> DataUpdateProcessResult {
112118

113119
let context = privateQueueManagedObjectContext
114120

115121
return try! context.performErrorBlockAndWait {
116122

117123
guard let summit = try SummitManagedObject.find(summit, context: context)
118-
else { return false }
124+
else { return .success(false) }
119125

120126
#if os(iOS)
121127
let authenticatedMember = try self.authenticatedMember(context)
122128
#else
123129
let authenticatedMember: MemberManagedObject? = nil
124130
#endif
125131

132+
// truncate if dataupdate is older than a week
133+
guard Calendar.current.isDate(dataUpdate.date, equalTo: Date(), toGranularity: .weekOfYear) else {
134+
135+
try self.clear(forceLogout: false)
136+
137+
return .dataWipe
138+
}
139+
126140
// truncate
127141
guard dataUpdate.operation != .truncate else {
128142

129143
guard dataUpdate.className == .WipeData
130-
else { return false }
144+
else { return .success(false) }
131145

132146
try self.clear()
133147

134-
#if os(iOS)
135-
self.logout()
136-
#endif
137-
138-
return true
148+
return .dataWipe
139149
}
140150

141151
guard dataUpdate.className != .WipeData
142-
else { return false }
152+
else { return .success(false) }
143153

144154
// add or remove to schedule
145155
guard dataUpdate.className != .MySchedule else {
146156

147157
// should only get for authenticated requests
148158
guard let member = authenticatedMember
149-
else { return false }
159+
else { return .success(false) }
150160

151161
switch dataUpdate.operation {
152162

@@ -155,28 +165,28 @@ public extension Store {
155165
guard let entityJSON = dataUpdate.entity,
156166
case let .json(jsonObject) = entityJSON,
157167
let event = Event.DataUpdate.init(json: .object(jsonObject))
158-
else { return false }
168+
else { return .success(false) }
159169

160170
let eventManagedObject = try event.write(context, summit: summit) as! EventManagedObject
161171

162172
member.schedule.insert(eventManagedObject)
163173

164-
return true
174+
return .success(true)
165175

166176
case .delete:
167177

168178
guard let entityID = dataUpdate.entity,
169179
case let .identifier(identifier) = entityID
170-
else { return false }
180+
else { return .success(false) }
171181

172182
if let eventManagedObject = try EventManagedObject.find(identifier, context: context) {
173183

174184
member.schedule.remove(eventManagedObject)
175185
}
176186

177-
return true
187+
return .success(true)
178188

179-
default: return false
189+
default: return .success(false)
180190
}
181191
}
182192

@@ -185,7 +195,7 @@ public extension Store {
185195

186196
// should only get for authenticated requests
187197
guard let member = authenticatedMember
188-
else { return false }
198+
else { return .success(false) }
189199

190200
switch dataUpdate.operation {
191201

@@ -194,56 +204,56 @@ public extension Store {
194204
guard let entityJSON = dataUpdate.entity,
195205
case let .json(jsonObject) = entityJSON,
196206
let event = Event.DataUpdate.init(json: .object(jsonObject))
197-
else { return false }
207+
else { return .success(false) }
198208

199209
let eventManagedObject = try event.write(context, summit: summit) as! EventManagedObject
200210

201211
member.favoriteEvents.insert(eventManagedObject)
202212

203-
return true
213+
return .success(true)
204214

205215
case .delete:
206216

207217
guard let entityID = dataUpdate.entity,
208218
case let .identifier(identifier) = entityID
209-
else { return false }
219+
else { return .success(false) }
210220

211221
if let eventManagedObject = try EventManagedObject.find(identifier, context: context) {
212222

213223
member.favoriteEvents.remove(eventManagedObject)
214224
}
215225

216-
return true
226+
return .success(true)
217227

218-
default: return false
228+
default: return .success(false)
219229
}
220230
}
221231

222232
/// we dont support all of the DataUpdate types, but thats ok
223233
guard let type = dataUpdate.className.type
224-
else { return true }
234+
else { return .success(true) }
225235

226236
// delete
227237
guard dataUpdate.operation != .delete else {
228238

229239
guard let entityID = dataUpdate.entity,
230240
case let .identifier(identifier) = entityID
231-
else { return false }
241+
else { return .success(false) }
232242

233243
// if it doesnt exist, dont delete it
234244
if let foundEntity = try type.find(identifier, context: context) {
235245

236246
context.delete(foundEntity)
237247
}
238248

239-
return true
249+
return .success(true)
240250
}
241251

242252
// parse JSON
243253
guard let entityJSON = dataUpdate.entity,
244254
case let .json(jsonObject) = entityJSON,
245255
let entity = type.init(json: .object(jsonObject))
246-
else { return false }
256+
else { return .success(false) }
247257

248258
switch dataUpdate.className {
249259

@@ -252,28 +262,28 @@ public extension Store {
252262
guard let image = entity as? Image
253263
else { return false }
254264
*/
255-
return true
265+
return .success(true)
256266

257267
case .SummitGroupEvent:
258268

259269
guard let member = authenticatedMember,
260270
let event = entity as? GroupEventDataUpdate
261-
else { return false }
271+
else { return .success(false) }
262272

263273
// insert or update
264274
let managedObject = try event.save(context)
265275

266276
// add to authenticated member's group events
267277
member.groupEvents.insert(managedObject)
268278

269-
return true
279+
return .success(true)
270280

271281
default:
272282

273283
// insert or update
274284
let _ = try entity.write(context, summit: summit)
275285

276-
return true
286+
return .success(true)
277287
}
278288
}
279289
}

OpenStack Summit/CoreSummit/DataUpdatePoller.swift

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public final class DataUpdatePoller {
1212

1313
public var polling = false
1414

15-
public var pollingInterval: Double = 60
15+
public var pollingInterval: Double = 30
1616

1717
public var log: ((String) -> ())?
1818

@@ -68,14 +68,7 @@ public final class DataUpdatePoller {
6868
// dont poll if no active summit
6969
guard let summitID = self.summit,
7070
let summit = try! SummitManagedObject.find(summitID, context: store.managedObjectContext)
71-
else {
72-
// clear latest data update after wipe
73-
if let latestDataUpdate = storage.latestDataUpdate {
74-
75-
storage.clear()
76-
}
77-
return
78-
}
71+
else { return }
7972

8073
print("Polling server for data updates for summit \(summitID)")
8174

@@ -98,25 +91,33 @@ public final class DataUpdatePoller {
9891

9992
let update = dataUpdates[index]
10093

101-
if store.process(dataUpdate: update, summit: summit.id) == false {
94+
let result = store.process(dataUpdate: update, summit: summit.id)
95+
96+
if case let .success(value) = result {
10297

103-
// could not process update
98+
if !value {
99+
100+
// could not process update
101+
102+
log?("Could not process: \(update.identifier)")
103+
104+
#if DEBUG
105+
return // block
106+
#endif
107+
}
104108

105-
log?("Could not process: \(update.identifier)")
109+
// store latest data update
110+
storage.latestDataUpdate = update.identifier
106111

107-
#if DEBUG
108-
return // block
109-
#endif
112+
processedCount = index
110113
}
111114

112-
// store latest data update
113-
storage.latestDataUpdate = update.identifier
114-
115-
processedCount = index
116-
117-
// exit loop if data wiping
118-
if update.className == .WipeData &&
119-
update.operation == .truncate {
115+
// clear data pooler storage and exit loop if data wiping
116+
if case .dataWipe = result {
117+
118+
print("Data wiping")
119+
120+
storage.clear()
120121

121122
break
122123
}
@@ -128,7 +129,7 @@ public final class DataUpdatePoller {
128129

129130
try! context.performErrorBlockAndWait { try context.validateAndSave() }
130131

131-
print("Processed \(processedCount) data updates")
132+
if processedCount > 0 { print("Processed \(processedCount + 1) data updates") }
132133
}
133134
}
134135

@@ -137,6 +138,8 @@ public final class DataUpdatePoller {
137138

138139
// execute request
139140

141+
polling = true
142+
140143
if let latestDataUpdate = storage.latestDataUpdate {
141144

142145
store.dataUpdates(summit.id, latestDataUpdate: latestDataUpdate) { process(response: $0) }
@@ -145,8 +148,6 @@ public final class DataUpdatePoller {
145148

146149
store.dataUpdates(summit.id, from: summit.initialDataLoad ?? Date()) { process(response: $0) }
147150
}
148-
149-
polling = true
150151
}
151152
}
152153

OpenStack Summit/CoreSummit/Login.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ public extension Store {
3737

3838
session.clear()
3939

40+
// clear tokens
41+
oauthModuleOpenID.oauth2Session.clearTokens()
42+
4043
NotificationCenter.default.post(name: Store.Notification.loggedOut, object: self)
4144
}
4245

OpenStack Summit/CoreSummit/MemberRequest.swift

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,26 +23,40 @@ public extension Store {
2323

2424
let context = privateQueueManagedObjectContext
2525

26-
http.request(method: .get, path: url) { (responseObject, error) in
26+
if let authModule = http.authzModule {
2727

28-
// forward error
29-
guard error == nil
30-
else { completion(.error(error!)); return }
31-
32-
guard let json = try? JSON.Value(string: responseObject as! String),
33-
let member = MemberResponse.Member(json: json)
34-
else { completion(.error(Error.invalidResponse)); return }
35-
36-
// cache
37-
try! context.performErrorBlockAndWait {
28+
if authModule.isAuthorized() {
3829

39-
let _ = try member.save(context)
30+
http.request(method: .get, path: url) { (responseObject, error) in
31+
32+
// forward error
33+
guard error == nil
34+
else { completion(.error(error!)); return }
35+
36+
guard let json = try? JSON.Value(string: responseObject as! String),
37+
let member = MemberResponse.Member(json: json)
38+
else { completion(.error(Error.invalidResponse)); return }
39+
40+
// cache
41+
try! context.performErrorBlockAndWait {
42+
43+
let _ = try member.save(context)
44+
45+
try context.validateAndSave()
46+
}
47+
48+
// success
49+
completion(.value(member))
50+
}
51+
}
52+
else {
4053

41-
try context.validateAndSave()
54+
completion(.error(Store.Error.unauthorized))
4255
}
56+
}
57+
else {
4358

44-
// success
45-
completion(.value(member))
59+
completion(.error(Store.Error.customClientError("OAuth module not configured")))
4660
}
4761
}
4862
}

0 commit comments

Comments
 (0)