Skip to content

Commit

Permalink
Merge pull request #1850 from RADAR-base/release-3.3.3-alpha
Browse files Browse the repository at this point in the history
Release 3.3.3-alpha
  • Loading branch information
mpgxvii authored Jan 28, 2025
2 parents 81cf890 + 611c6af commit 83983d9
Show file tree
Hide file tree
Showing 19 changed files with 276 additions and 186 deletions.
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ android {
applicationId "org.phidatalab.radar_armt"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 590
versionName "3.3.2-alpha"
versionCode 592
versionName "3.3.3-alpha"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
aaptOptions {
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
Expand Down
4 changes: 2 additions & 2 deletions ios/App/App.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@
INFOPLIST_FILE = App/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 3.3.2;
MARKETING_VERSION = 3.3.3;
OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
PRODUCT_BUNDLE_IDENTIFIER = "org.phidatalab.radar-armt";
PRODUCT_NAME = "$(TARGET_NAME)";
Expand All @@ -388,7 +388,7 @@
INFOPLIST_FILE = App/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 3.3.2;
MARKETING_VERSION = 3.3.3;
PRODUCT_BUNDLE_IDENTIFIER = "org.phidatalab.radar-armt";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "";
Expand Down
13 changes: 11 additions & 2 deletions ios/App/App/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>3.3.2</string>
<string>3.3.3</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
Expand All @@ -32,7 +32,16 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>2</string>
<string>1</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>org.phidatalab.radar-armt</string>
</array>
</dict>
</array>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSCameraUsageDescription</key>
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "radar-questionnaire",
"description": "An application that collects active data for research.",
"version": "3.3.2",
"version": "3.3.3",
"author": "RADAR Base",
"homepage": "http://www.radar-base.org/",
"scripts": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ export abstract class FcmNotificationService extends NotificationService {
if (token) {
this.FCM_TOKEN = token
return this.setFCMToken(token).then(() =>
this.logger.log('[NOTIFICATION SERVICE] Refresh token success')
this.logger.log('[NOTIFICATION SERVICE] Refresh FCM token success')
)
} else {
return Promise.resolve()
Expand Down
58 changes: 47 additions & 11 deletions src/app/core/services/token/token.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ import { Platform } from '@ionic/angular'

import {
DefaultEndPoint,
DefaultManagementPortalURI,
DefaultOAuthClientId,
DefaultOAuthClientSecret,
DefaultRefreshTokenURI,
DefaultRequestEncodedContentType,
DefaultTokenEndPoint,
DefaultTokenRefreshSeconds
} from '../../../../assets/data/defaultConfig'
import { ConfigKeys } from '../../../shared/enums/config'
Expand All @@ -26,7 +25,8 @@ import { StorageService } from '../storage/storage.service'
export class TokenService {
private readonly TOKEN_STORE = {
OAUTH_TOKENS: StorageKeys.OAUTH_TOKENS,
BASE_URI: StorageKeys.BASE_URI
BASE_URI: StorageKeys.BASE_URI,
TOKEN_ENDPOINT: StorageKeys.TOKEN_ENDPOINT
}
URI_base: string
private tokenRefreshMillis: number = DefaultTokenRefreshSeconds
Expand Down Expand Up @@ -65,6 +65,12 @@ export class TokenService {
.then(uri => (uri ? uri : DefaultEndPoint))
}

getTokenEndpoint() {
return this.storage
.get(this.TOKEN_STORE.TOKEN_ENDPOINT)
.then(uri => (uri ? uri : DefaultTokenEndPoint))
}

setTokens(tokens) {
return this.storage.set(this.TOKEN_STORE.OAUTH_TOKENS, tokens)
}
Expand All @@ -78,20 +84,23 @@ export class TokenService {
return this.storage.set(this.TOKEN_STORE.BASE_URI, url).then(() => url)
}

setTokenEndpoint(uri: string) {
return this.storage.set(this.TOKEN_STORE.TOKEN_ENDPOINT, uri)
}

static basicCredentials(user: string, password: string): string {
return 'Basic ' + btoa(`${user}:${password}`)
}

register(refreshBody): Promise<OAuthToken> {
return Promise.all([
this.getURI(),
this.getTokenEndpoint(),
this.getRegisterHeaders(DefaultRequestEncodedContentType)
])
.then(([uri, headers]) => {
const URI = uri + DefaultManagementPortalURI + DefaultRefreshTokenURI
this.logger.log(`"Registering with ${URI} and headers`, headers)
this.logger.log(`"Registering with ${uri} and headers`, headers)
return this.http
.post(URI, refreshBody, { headers: headers })
.post(uri, refreshBody, { headers: headers })
.toPromise()
})
.then(res => this.setTokens(res).then(() => res))
Expand All @@ -107,7 +116,19 @@ export class TokenService {
})
if (tokens.iat + tokens.expires_in < limit) {
const params = this.getRefreshParams(tokens.refresh_token)
return this.register(params)
return this.register(params).catch(response => {
const error = response.error
if (error && error.error === 'invalid_grant') {
// Specific check for expired refresh token
console.error('Refresh token expired. Please log in again.')
this.reset() // Clear tokens and session data
throw new Error('Session expired. Please log in again.')
}

// Handle other errors (e.g., network, server issues)
console.error('Error refreshing token:', error)
throw new Error('Error refreshing token. Please try again.')
})
} else {
return tokens
}
Expand Down Expand Up @@ -155,9 +176,24 @@ export class TokenService {
}

isValid(): Promise<boolean> {
return this.storage
.get(StorageKeys.OAUTH_TOKENS)
.then(tokens => !this.jwtHelper.isTokenExpired(tokens.refresh_token))
return this.storage.get(StorageKeys.OAUTH_TOKENS).then(tokens => {
if (!tokens || !tokens.refresh_token) {
return false // No token available
}

const refreshToken = tokens.refresh_token

// Check if the token is a JWT (simple heuristic: contains three parts separated by dots)
const isJwt = refreshToken.split('.').length === 3

if (isJwt) {
// For JWT tokens, check expiration
return !this.jwtHelper.isTokenExpired(refreshToken)
} else {
// For opaque tokens, assume valid until refreshed
return true
}
})
}

reset() {
Expand Down
2 changes: 1 addition & 1 deletion src/app/pages/auth/auth.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@ const routes: Routes = [
providers: [AuthService, AuthGuard],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AuthModule {}
export class AuthModule { }
5 changes: 4 additions & 1 deletion src/app/pages/auth/components/qr-form/qr-form.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Component, EventEmitter, Input, Output } from '@angular/core'
import { BarcodeScanner } from '@capacitor-mlkit/barcode-scanning'
import { UsageService } from 'src/app/core/services/usage/usage.service'
import { UsageEventType } from 'src/app/shared/enums/events'

@Component({
selector: 'qr-form',
Expand All @@ -13,7 +15,7 @@ export class QRFormComponent {
@Output()
data: EventEmitter<any> = new EventEmitter<any>()

constructor() {}
constructor(private usage: UsageService) {}

async scanQRHandler() {
document.querySelector('body').classList.add('scanner-active')
Expand All @@ -33,5 +35,6 @@ export class QRFormComponent {
}
)
await BarcodeScanner.startScan() // start scanning and wait for a result
this.usage.sendGeneralEvent(UsageEventType.QR_SCANNED)
}
}
116 changes: 37 additions & 79 deletions src/app/pages/auth/containers/enrolment-page.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,21 @@
<div class="text">
<div class="text-lg">{{ 'ENROL_WELCOME_1' | translate }}</div>
{{ 'ENROL_WELCOME_2' | translate }}
<div class="padding text-justify extra-padding">
<div class="spn-container" *ngIf="loading | async">
<ion-spinner name="lines"></ion-spinner>
</div>
<div class="padding text-justify extra-padding" *ngIf="!(loading | async)">
<ion-item no-lines>
<span class="info-value">{{ language.label | translate }}</span>
<span slot="end" (click)="showSelectLanguage()">
<ion-icon
class="space-right"
name="caret-down-outline"
></ion-icon>
<ion-icon class="space-right" name="caret-down-outline"></ion-icon>
{{ 'BTN_SELECT' | translate }}
</span>
</ion-item>
</div>
</div>
<div class="bottom">
<ion-button
ion-button
class="bt bt--full"
round
full
(click)="next()"
>
<div class="bottom" *ngIf="!(loading | async)">
<ion-button ion-button class="bt bt--full" round full (click)="next()">
{{ 'BTN_START' | translate }}
</ion-button>
</div>
Expand Down Expand Up @@ -68,24 +62,12 @@
</div>
<div class="bottom">
<p>
<ion-button
ion-button
class="bt bt--full"
round
full
(click)="next()"
>
<ion-button ion-button class="bt bt--full" round full (click)="enrol('qr')">
{{ 'BTN_ENROL_SCAN' | translate }}
</ion-button>
</p>
<p>
<ion-button
ion-button
class="bt bt--full"
round
full
(click)="enterToken()"
>
<ion-button ion-button class="bt bt--full" round full (click)="enrol('token')">
{{ 'BTN_ENROL_ENTER_TOKEN' | translate }}
</ion-button>
</p>
Expand All @@ -98,66 +80,48 @@
<ion-card>
<div class="registration">
<div class="text text-lg">{{ 'ENROL_REGISTRATION' | translate }}</div>
<ng-container *ngIf="enterMetaQR">
<token-form
[loading]="loading"
(data)="authenticate($event)"
(focus)="clearStatus()"
(errors)="handleError($event)"
></token-form>
</ng-container>
<ng-container *ngIf="!enterMetaQR">
<qr-form
[loading]="loading"
(data)="authenticate($event)"
></qr-form>
</ng-container>
<div [ngSwitch]="enrolmentMethod">
<ng-container *ngSwitchCase="'token'">
<token-form [loading]="loading | async" (data)="authenticate($event)" (focus)="clearStatus()"
(errors)="handleError($event)"></token-form>
</ng-container>
<ng-container *ngSwitchCase="'qr'">
<qr-form [loading]="loading | async" (data)="authenticate($event)"></qr-form>
</ng-container>
</div>
</div>
</ion-card>
<div class="status">
<div id="outcome" *ngIf="showOutcomeStatus">
{{ outcomeStatus }}
</div>
<div id="loading" *ngIf="loading && !showOutcomeStatus">
<div id="loading" *ngIf="(loading | async) && !showOutcomeStatus">
{{ 'STATUS_LOADING' | translate }}...
</div>
</div>
</swiper-slide>

<!-- SLIDE 5 -->
<swiper-slide id="privacy-policy">
<ion-card>
<div class="registration">
<div class="text-lg">{{ 'ENROL_REGISTRATION' | translate }}</div>
<ion-card>
<div class="registration">
<div class="text-lg">{{ 'ENROL_REGISTRATION' | translate }}</div>

<div dir="auto" class="text text-justify">
{{ 'ENROL_PRIVACY_POLICY_DESC' | translate }}
</div>
<div class="padding text-justify extra-padding">
</div>
</div>
<div class="bottom">
<ion-button
ion-button
class="bt bt--full policy"
round
full
(click)="showPrivacyPolicy()"
>
{{ 'BTN_VIEW_POLICY' | translate }}
</ion-button>
<ion-button
ion-button
class="bt bt--full"
round
full
(click)="next()"
>
{{ 'BTN_NEXT' | translate }}
</ion-button>
<div dir="auto" class="text text-justify">
{{ 'ENROL_PRIVACY_POLICY_DESC' | translate }}
</div>
</ion-card>
</swiper-slide>
<div class="padding text-justify extra-padding"></div>
</div>
<div class="bottom">
<ion-button ion-button class="bt bt--full policy" round full (click)="showPrivacyPolicy()">
{{ 'BTN_VIEW_POLICY' | translate }}
</ion-button>
<ion-button ion-button class="bt bt--full" round full (click)="next()">
{{ 'BTN_NEXT' | translate }}
</ion-button>
</div>
</ion-card>
</swiper-slide>

<!-- SLIDE 6 -->
<swiper-slide id="registration-complete">
Expand All @@ -173,13 +137,7 @@
</div>

<div class="bottom">
<ion-button
ion-button
class="bt bt--full"
round
full
(click)="navigateToSplash()"
>
<ion-button ion-button class="bt bt--full" round full (click)="navigateToSplash()">
{{ 'BTN_FINISH' | translate }}
</ion-button>
</div>
Expand Down
Loading

0 comments on commit 83983d9

Please sign in to comment.