Skip to content

Commit 7184790

Browse files
Merge pull request #104 from cuappdev/preston/goals-onboarding
[Goals for Onboarding]
2 parents f106f71 + b6937eb commit 7184790

14 files changed

Lines changed: 435 additions & 97 deletions

File tree

.DS_Store

-6 KB
Binary file not shown.

app/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ dependencies {
127127
implementation 'com.google.firebase:firebase-auth'
128128
implementation 'com.google.firebase:firebase-messaging'
129129
implementation("com.google.firebase:firebase-analytics")
130+
implementation "androidx.security:security-crypto:1.1.0-alpha06"
130131
}
131132

132133
apollo {

app/src/main/graphql/User.graphql

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ query getUserByNetId($netId: String!) {
3333
}
3434
}
3535

36-
mutation SetWorkoutGoals($id: Int!, $workoutGoal: [String!]!) {
36+
mutation SetWorkoutGoals($id: Int!, $workoutGoal: Int!) {
3737
setWorkoutGoals(userId: $id, workoutGoal: $workoutGoal) {
3838
...userFields
3939
}
@@ -43,4 +43,17 @@ mutation LogWorkout($facilityId: Int!, $workoutTime: DateTime!, $id: Int!) {
4343
logWorkout(facilityId: $facilityId, userId: $id, workoutTime: $workoutTime) {
4444
...workoutFields
4545
}
46-
}
46+
}
47+
48+
mutation DeleteUser($userId: Int!) {
49+
deleteUser(userId: $userId) {
50+
...userFields
51+
}
52+
}
53+
54+
mutation LoginUser($netId: String!) {
55+
loginUser(netId: $netId) {
56+
accessToken
57+
refreshToken
58+
}
59+
}

app/src/main/graphql/schema.graphqls

Lines changed: 60 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,6 @@ type Query {
3636
"""
3737
getAllReports: [Report]
3838

39-
"""
40-
Get the workout goals of a user by ID.
41-
"""
42-
getWorkoutGoals(id: Int!): [String]
43-
44-
"""
45-
Get the current and max workout streak of a user.
46-
"""
47-
getUserStreak(id: Int!): JSONString
48-
4939
"""
5040
Get all facility hourly average capacities.
5141
"""
@@ -358,39 +348,39 @@ type User {
358348

359349
name: String!
360350

361-
activeStreak: Int
351+
activeStreak: Int!
352+
353+
maxStreak: Int!
354+
355+
workoutGoal: Int
362356

363-
maxStreak: Int
357+
lastGoalChange: DateTime
364358

365-
workoutGoal: [DayOfWeekGraphQLEnum]
359+
lastStreak: Int!
366360

367361
encodedImage: String
368362

369363
giveaways: [Giveaway]
370364

365+
goalHistory: [WorkoutGoalHistory]
366+
371367
friendRequestsSent: [Friendship]
372368

373369
friendRequestsReceived: [Friendship]
374370

375371
friendships: [Friendship]
376372

377373
friends: [User]
378-
}
379-
380-
enum DayOfWeekGraphQLEnum {
381-
MONDAY
382-
383-
TUESDAY
384-
385-
WEDNESDAY
386-
387-
THURSDAY
388-
389-
FRIDAY
390374

391-
SATURDAY
375+
"""
376+
Get the total number of gym days (unique workout days) for user.
377+
"""
378+
totalGymDays: Int!
392379

393-
SUNDAY
380+
"""
381+
The start date of the most recent active streak, up until the current date.
382+
"""
383+
streakStart: Date
394384
}
395385

396386
type Giveaway {
@@ -401,6 +391,18 @@ type Giveaway {
401391
users: [User]
402392
}
403393

394+
type WorkoutGoalHistory {
395+
id: ID!
396+
397+
userId: Int!
398+
399+
workoutGoal: Int!
400+
401+
effectiveAt: DateTime!
402+
403+
user: User
404+
}
405+
404406
type Friendship {
405407
id: ID!
406408

@@ -419,6 +421,13 @@ type Friendship {
419421
friend: User
420422
}
421423

424+
"""
425+
The `Date` scalar type represents a Date
426+
value as specified by
427+
[iso8601](https://en.wikipedia.org/wiki/ISO_8601).
428+
"""
429+
scalar Date
430+
422431
type Workout {
423432
id: ID!
424433

@@ -427,12 +436,9 @@ type Workout {
427436
userId: Int!
428437

429438
facilityId: Int!
430-
}
431439

432-
"""
433-
JSON String
434-
"""
435-
scalar JSONString
440+
gymName: String!
441+
}
436442

437443
type HourlyAverageCapacity {
438444
id: ID!
@@ -448,6 +454,22 @@ type HourlyAverageCapacity {
448454
history: [Float]!
449455
}
450456

457+
enum DayOfWeekGraphQLEnum {
458+
MONDAY
459+
460+
TUESDAY
461+
462+
WEDNESDAY
463+
464+
THURSDAY
465+
466+
FRIDAY
467+
468+
SATURDAY
469+
470+
SUNDAY
471+
}
472+
451473
type CapacityReminder {
452474
id: ID!
453475

@@ -518,7 +540,7 @@ type Mutation {
518540
"""
519541
Set a user's workout goals.
520542
"""
521-
setWorkoutGoals("The ID of the user." userId: Int!, "The new workout goal for the user in terms of days of the week." workoutGoal: [String]!): User
543+
setWorkoutGoals("The ID of the user." userId: Int!, "The new workout goal for the user in terms of number of days per week." workoutGoal: Int!): User
522544

523545
"""
524546
Log a user's workout.
@@ -545,6 +567,11 @@ type Mutation {
545567
"""
546568
createReport(createdAt: DateTime!, description: String!, gymId: Int!, issue: String!): CreateReport
547569

570+
"""
571+
Deletes a report by ID.
572+
"""
573+
deleteReport(reportId: Int!): Report
574+
548575
"""
549576
Deletes a user by ID.
550577
"""
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.cornellappdev.uplift.data.repositories
2+
3+
import okhttp3.Interceptor
4+
import okhttp3.Response
5+
import javax.inject.Inject
6+
import javax.inject.Singleton
7+
8+
@Singleton
9+
class AuthInterceptor @Inject constructor(
10+
private val tokenManager: TokenManager
11+
) : Interceptor {
12+
override fun intercept(chain: Interceptor.Chain): Response {
13+
val token = tokenManager.getAccessToken()
14+
val request = chain.request().newBuilder().apply {
15+
if (token != null) {
16+
addHeader("Authorization", "Bearer $token")
17+
}
18+
}.build()
19+
return chain.proceed(request)
20+
}
21+
}

app/src/main/java/com/cornellappdev/uplift/data/repositories/DatastoreRepository.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ object PreferencesKeys {
2525
val USERNAME = stringPreferencesKey("username")
2626
val NETID = stringPreferencesKey("netId")
2727
val EMAIL = stringPreferencesKey("email")
28+
val GOAL = intPreferencesKey("workoutGoal")
2829
val SKIP = booleanPreferencesKey("skip")
2930
val FCM_TOKEN = stringPreferencesKey("fcmToken")
3031
val DECLINED_NOTIFICATION_PERMISSION =
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package com.cornellappdev.uplift.data.repositories
2+
3+
import android.content.Context
4+
import android.content.SharedPreferences
5+
import android.util.Log
6+
import androidx.security.crypto.EncryptedSharedPreferences
7+
import androidx.security.crypto.MasterKey
8+
import androidx.core.content.edit
9+
import dagger.hilt.android.qualifiers.ApplicationContext
10+
import javax.inject.Inject
11+
import javax.inject.Singleton
12+
13+
@Singleton
14+
class TokenManager @Inject constructor(@ApplicationContext private val context: Context) {
15+
private val fileName = "encrypted_tokens"
16+
17+
// Initialize EncryptedSharedPreferences
18+
private val sharedPreferences: SharedPreferences? by lazy {
19+
try {
20+
createEncryptedPrefs()
21+
} catch (e: Exception) {
22+
Log.e("TokenManager", "Failed to initialize EncryptedSharedPreferences", e)
23+
// Clear corrupted state
24+
context.deleteSharedPreferences(fileName)
25+
try {
26+
// Could have failed due to previous corrupted state
27+
// One more attempt after cleaning the corruption
28+
createEncryptedPrefs()
29+
} catch (retryException: Exception) {
30+
// Probably broken return null
31+
Log.e("TokenManager", "Failed to initialize EncryptedSharedPreferences again", retryException)
32+
null
33+
}
34+
}
35+
}
36+
37+
private fun createEncryptedPrefs(): SharedPreferences {
38+
val masterKey = MasterKey.Builder(context)
39+
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
40+
.build()
41+
42+
return EncryptedSharedPreferences.create(
43+
context,
44+
fileName,
45+
masterKey,
46+
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
47+
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
48+
)
49+
}
50+
51+
fun saveTokens(accessToken: String, refreshToken: String) {
52+
sharedPreferences?.edit {
53+
putString("access_token", accessToken)
54+
putString("refresh_token", refreshToken)
55+
}
56+
}
57+
58+
fun getAccessToken(): String? = sharedPreferences?.getString("access_token", null)
59+
60+
fun getRefreshToken(): String? = sharedPreferences?.getString("refresh_token", null)
61+
62+
fun clearTokens() {
63+
sharedPreferences?.edit { clear() }
64+
}
65+
}

0 commit comments

Comments
 (0)