oauthService.getIdentityClaims() returns null when using angular-oauth2-oidc and keycloak

I’m working on angular-oauth2-oidc and keycloak. I can login (redirecting to keycloak login page), and session has created inside keycloak for loggedin user.

However, oauthService.getIdentityClaims() returns null so I can’t get the username from this:

Below is my code:

environment.ts

export const environment = {
  production: false,
  envName: 'local',
  keycloak:{
    issuer:"http://localhost:8080/auth/realms/MySSOApp",
    redirectUri:"http://localhost:4202/",
    clientId:"sso-app3-client",
    scope:"openid profile email"
  }
};

sso-config.ts

import { AuthConfig } from 'angular-oauth2-oidc';
import { environment } from 'src/environments/environment';

export const authCodeFlowConfig: AuthConfig = {
    // Url of the Identity Provider
    issuer: environment.keycloak.issuer,

    redirectUri: environment.keycloak.redirectUri,

    clientId: environment.keycloak.clientId,

    // dummyClientSecret: 'secret',

    responseType: 'code',

    scope: environment.keycloak.scope,

    requireHttps: false,    

    showDebugInformation: true,

    disableAtHashCheck: true,

    strictDiscoveryDocumentValidation: false
};

export class OAuthModuleConfig {
    resourceServer: OAuthResourceServerConfig = {sendAccessToken: false};
}

export class OAuthResourceServerConfig {
   
    allowedUrls?: Array<string>;
    sendAccessToken = true;
    customUrlValidation?: (url: string) => boolean;
}

app.component.ts

import { Component, ViewChild } from '@angular/core';
import { OAuthService, NullValidationHandler } from 'angular-oauth2-oidc';
import { authCodeFlowConfig } from 'src/app/sso-config';
import { filter } from 'rxjs/operators';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent {
  title = 'sso-app';

  name: string = "";
  private _decodedAccessToken: any;
  private _decodedIDToken: any;
  get decodedAccessToken() { return this._decodedAccessToken; }
  get decodedIDToken() { return this._decodedIDToken; }

  @ViewChild('yourChild' /* #name or Type*/, {static: false}) child: any;

  constructor(private oauthService: OAuthService) {
  }

  ngOnInit() {
    //this.initAuth();
  }

  async initAuth(): Promise<any> {
    return new Promise<void>((resolveFn, rejectFn) => {
      // setup oauthService
      this.oauthService.configure(authCodeFlowConfig);
      this.oauthService.setStorage(localStorage);
      this.oauthService.tokenValidationHandler = new NullValidationHandler();

      // subscribe to token events
      this.oauthService.events.pipe(filter((e: any) => {
        console.log("e : ", e);
        return e.type === 'token_received';
      })).subscribe(() => {
        console.log("here..");
        this.handleNewToken();
      });

      this.oauthService.loadDiscoveryDocumentAndLogin().then(isLoggedIn => {
        console.log("isLoggedIn: ", isLoggedIn);
        if (isLoggedIn) {
          this.oauthService.setupAutomaticSilentRefresh();
          resolveFn();
        } else {          
          this.oauthService.initImplicitFlow();
          rejectFn();
        }
      });

    });
  }

  private handleNewToken() {
    this._decodedAccessToken = this.oauthService.getAccessToken();
    this._decodedIDToken = this.oauthService.getIdToken();
  }

}

navbar.component.ts

import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import { OAuthService } from 'angular-oauth2-oidc';

@Component({
  selector: 'app-navbar',
  templateUrl: './navbar.component.html',
  styleUrls: ['./navbar.component.css']
})
export class NavbarComponent implements OnInit {

  name: string = "";

  constructor(private oauthService: OAuthService) { }

  @Output() someEvent = new EventEmitter<any>();

  givenName:any;

  ngOnInit(): void {
    const userClaims: any = this.oauthService.getIdentityClaims();
    console.log(userClaims);
    if(userClaims){
      this.givenName = userClaims.name ? userClaims.name : "";
    }    
  }

  login() {    
      this.someEvent.next('somePhone');
  }

  logout() {
    this.oauthService.logOut();
  }

  // get givenName() {
  //   const claims: any = this.oauthService.getIdentityClaims();
  //   console.log("Claims ======>>>>>>", claims);
  //   if (!claims) {
  //     return null;
  //   }
  //   return claims['name'];
  // }

}

app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { NavbarComponent } from './components/navbar/navbar.component';
import { HomeComponent } from './components/home/home.component';
import { WelcomeComponent } from './components/welcome/welcome.component';
import { Routes, RouterModule, Router } from '@angular/router';
import { HttpClientModule } from '@angular/common/http';
import { AuthConfig, OAuthModule, OAuthService, OAuthStorage } from 'angular-oauth2-oidc';
import { AuthGuard } from './auth.guard';
import { authCodeFlowConfig, OAuthModuleConfig } from './sso-config';

const routes: Routes = [
  { path: 'home', component: HomeComponent, canActivate: [AuthGuard] },
  { path: 'welcome', component: WelcomeComponent },
  { path: '', redirectTo: '/welcome', pathMatch: 'full' }, // anything that didn't match above routes then redirect to products
  { path: '**', redirectTo: '/welcome', pathMatch: 'full' }, // anything that didn't match above routes then redirect to products
];

@NgModule({
  declarations: [
    AppComponent,
    NavbarComponent,
    HomeComponent,
    WelcomeComponent
  ],
  imports: [
    RouterModule.forRoot(routes),
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    BrowserAnimationsModule,
    OAuthModule.forRoot()
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

auth.guard.ts

import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router';
import { OAuthService } from 'angular-oauth2-oidc';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {

  constructor(private oauthService: OAuthService, private router: Router) {

  }

  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
    var hasIdToken = this.oauthService.hasValidIdToken();
    var hasAccessToken = this.oauthService.hasValidAccessToken();

    console.log("==", hasIdToken);
    console.log("==", hasAccessToken);

    if ((hasAccessToken)) {
      return true;
    }
    this.router.navigate(["/welcome"]);
    return false;
  }

}

Any idea what I needs to be done here to work it properly.

Thanks

Append items from one array to another, then if button is clicked on, move the last item back

I’m building a function to help me with moving items from the arrays. Component renders various sections:

  1. filledArray – an array of null’s, that produces a dynamic amount of buttons depending on the length of the word.
  2. bottomLetters – an array of letters, where the word has been split onto each individual letter. Once the letter is clicked on it will append a new item in filledArray.
  3. delete button – once clicked on, deletes the last item within the topLetter array and adds the back to the bottomLetters array..

Now I have two issues with the code:

  1. It does not update the render automatically. I’d have to save the code sandbox to generate the result.
  2. When clicking on delete button it breaks the value of the items in the bottomLetters array. (For example try clicking on three items from bottomLetters array, hit save and then hit delete button, it won’t move the items back to the array).

This is the code example that I have:
https://codesandbox.io/s/show-and-hide-in-react-forked-nh9l2?file=/src/MyApp.js

Remove mirrored objects from an array

I have an issue which I dont’t really know how to tackle in a good way

I have an array of objects which looks roughly like this:

[
    { name: "horse", newName: "owl" }
    { name: "owl", newName: "horse" }
    { name: "frog", newName: "dog" }
]

I want to remove “mirrored” objects from this array, in result having an array like this:

[
    { name: "frog", newName: "dog" }
]

Basically I need to find objects with opposite keys and values

More complex scenarios:

[
    { name: "horse", newName: "frog" }
    { name: "owl", newName: "horse" }
    { name: "frog", newName: "owl" }
]

    // Result: []
[
    { name: "horse", newName: "frog" }
    { name: "dog", newName: "cat" }
    { name: "owl", newName: "horse" }
    { name: "frog", newName: "owl" }
    { name: "monkey", newName: "worm" }
    { name: "cat", newName: "dog" }
]

    // Result: [{ name: "monkey", newName: "worm" }]

In the first case I would simply loop through the array and if an object like this is found:

{key: obj1.value, value: obj1.key} I would splice them both

But I have no idea how to approach the more complex situation when 3 or more objects would have to be removed. Any hints?

In advance thanks for your time

How to force OpenLayers to load source?

I have noticed that OpenLayers will not “load” source unless it is assigned to a layer which is assigned to map.

This code does console.log() with number of features in a KML layer:

const layer = new Heatmap({
  source: new VectorSource({
    url: file,
    format: new KML({
      extractStyles: false,
    }),
  }),
});

layer.getSource().on('change', function (evt: any) {
  var source = evt.target;
  if (source.getState() === 'ready') {
    var numFeatures = source.getFeatures().length;
    console.log('Count after change: ' + numFeatures);
  }
});

this.map.addLayer(layer);

If I remove this line:

this.map.addLayer(layer);

it doesn’t output anything. I have a feeling that OpenLayers ignores it as it is not used. Is there a way to force OpenLayers to load it?

(context – I would like to merge features coming from multiple sources into one thus I don’t want to directly load them onto the map. I’d like them to load so I can get features and then merge these features into one array and then display this array on the map)

Sending MailApp mail provided

such a question: There is a code that sends an email with the data of the cell “var RANGE” Under the condition “var check” > 10 in the “if” function What needs to be done to:

  1. The “var check” condition did not parse a single cell, but a range. (Just write Q123:Q126, it won’t work, the script is not executed) and the condition should not be >10, but equal to =10 since the trigger runs the function every day and checks the table.

  2. If the number 10 is in the “var check” range, then the entire line should be sent by email. If it doesn’t work out, then at least do it like this>

  3. “var RANGE” make it possible to selectively take cells (ex. B121:N129, R123:T129)

Can i get some advice?

var ID = "1sBtjJ9x4IKwb9GKu3x3DwoNWTxPej7HJWk5ze8aK"; //speadsheet id
var EMAIL = "[email protected]"; //email 
var RANGE = "Warranty_2021!B121:n129"; //data range to send
var check = "Warranty_2021!Q123:Q123"; //parametr
var text = "Servis"; //subject


function sendData() {
  var spreadsheet = SpreadsheetApp.openById(ID);
  var data = spreadsheet.getRangeByName(RANGE).getValues();
  var message = {};
  if (SpreadsheetApp.openById(ID).getRangeByName(check).getValues()>10){ //condition
  message.subject = "[La Test] " + text;
  message.to = EMAIL;
  message.htmlBody = dataToHtmlTable_(data) +
    "<br><br>[IT care you ;)]";
  MailApp.sendEmail(message);
  }
  let quota = MailApp.getRemainingDailyQuota();
  console.log(quota)
}

Array.prototype.datesToString = function(){
  return this.map(function(row){
    return row.map(function(cell){
      return cell && cell.getTime ? Utilities.formatDate(cell, Session.getScriptTimeZone(), "yyyy-MM-dd ") : cell;
    });
  });
}


function dataToHtmlTable_(data){
  return JSON.stringify(data, null, "  ")
  .replace(/^[/g, "<table>")
  .replace(/]$/g, "</table>")
  .replace(/^ss[$/mg, "<tr>")
  .replace(/^ss],{0,1}$/mg, "</tr>")
  .replace(/^s{4}"{0,1}(.*?)"{0,1},{0,1}$/mg, "<td>$1</td>");
}

is there better way coverting html string to DOM?

<div class="row data">
  <div class="subdiv">
    <div class="check"><input type="checkbox" name="buy" value="260" checked="" onclick="javascript:basket.checkItem();">&nbsp;</div>
    <div class="img"><img src="./img/basket1.jpg" width="60"></div>
    <div class="pname">
      <span>TX2</span>
    </div>
  </div>
  <div class="subdiv">
    <div class="num">
      <div class="updown">
        <input type="text" name="p_num1" id="p_num1" size="2" maxlength="4" class="p_num" value="2" onkeyup="javascript:basket.changePNum(1);">
        <span onclick="javascript:basket.changePNum(1);"><i class="fas fa-arrow-alt-circle-up up"></i></span>
        <span onclick="javascript:basket.changePNum(1);"><i class="fas fa-arrow-alt-circle-down down"></i></span>
      </div>
    </div>
  </div>
  <div class="subdiv">
    <div class="basketcmd"><a href="javascript:void(0)" class="abutton" onclick="javascript:basket.delItem();">삭제</a></div>
  </div>
</div>

I saw the way using DOMParser().parseFromString, but this solution requires me to convert html code into one line string. Is there better way to convert or skills to make html code to string easily?

my final goal is to use appendChild() so that I can have many “row data” class div. which requires me to make html code to DOM.

How to update a value in a complex fhirBundle JSON?

Given a bewildering fhir document like https://raw.githubusercontent.com/Notarise-gov-sg/api-notarise-healthcerts/master/test/fixtures/v2/pdt_art_with_nric_unwrapped.json

I need to update the part the JSON from { "id": "NRIC-FIN", "value": "S9098989Z" } to { "id": "NRIC-FIN", "value": "foobar" } and then emit the whole JSON again with that change.

I just about know how to access the value.

const fs = require("fs");
let rawdata = fs.readFileSync("pdt_art_with_nric_unwrapped.json");
let art = JSON.parse(rawdata);

let nric = art.fhirBundle.entry
  .flatMap((entry) => entry.resource)
  .find((entry) => entry.resourceType === "Patient")
  .identifier.find((entry) => entry.id === "NRIC-FIN").value;

console.log(nric);

Though I am puzzled how to update this value since it’s so difficult to access. Am I missing a trick? I don’t want to use regex btw!

is it possible to let different entry package to different output path in webpack 5

I am using webpack to package a google chrome extension, I want to keep the folder structure in the dist folder. for example, I want to package all popup resource in the dist/popup/*, this is my config right now:

const path = require('path');
const webpack = require( 'webpack' );
const MiniCssExtractPlugin = require( 'mini-css-extract-plugin');
const HtmlWebpackPlugin = require( 'html-webpack-plugin');
const CopyPlugin = require("copy-webpack-plugin");

module.exports = {
  entry : {
    popup : './src/popup/' 
  } ,
  resolve: {
    alias: {
        // https://stackoverflow.com/questions/50805384/module-not-found-error-cant-resolve-vue-path-not-correct
        vue: 'vue/dist/vue.esm-bundler.js'
    },
  },
  output : {
    path : path.resolve(__dirname, '../../bundle') ,
    filename : '[path]/[name].js'
  },
  module : {
    rules : [
      {
        test : /.js$/ ,
        exclude : [ /node_modules(?!(/|\?\)(translation.js|selection-widget|connect.io|chrome-env)1)/ ] ,
        loader : 'babel-loader'
      } ,
      {
        test: /.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
      {
        test : /.(scss)$/ ,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader']
      }
    ]
  },
  plugins : [
    new CopyPlugin({
      patterns: [
        { from: "src/manifest.json", to: "manifest.json" },
        { from: "src/resource/image", to: "resource/image" },
      ],
    }),
    new MiniCssExtractPlugin({
      filename: "[name].css",
      chunkFilename: "[id].css",
    }),
    new HtmlWebpackPlugin({
      filename: 'popup.html',
      template: 'src/popup/index.html'
    }),
    new webpack.DefinePlugin({
      __VUE_OPTIONS_API__: false,
      __VUE_PROD_DEVTOOLS__: false,
    }),
  ]
};

I have tried to tweak the output filename like this:

filename : '[path]/[name].js'

seems did not work. I am searching from google and did not found any suggestion. Is it possible to do like this? or different entry with different dist folder.

Three.Js Whenever i load an obj with objloader extra vertices are added to my object even after using indexed geometry

Hello so as the title says whenever i load an obj file with obj loader along with indexed geometry extra vertices are added to my object and i cant figure out why.

For example when i load my obj without indexed geometry the vertices are the same as the faces of the object ( from what i read this is because of triangle soup) after using BufferGeometryUtils.mergeVertices and then Computing Vertex Normals the vertice count went down almost to the original but not quite.

This is how i use obj loader

loader= new OBJLoader()
var textureLoader = new THREE.TextureLoader(loadingManager);
var map = textureLoader.load('Castle.jpg'); 
var material = new THREE.MeshPhysicalMaterial({map: map, vertexColors: true});

loader.load( 'Castle.obj', function ( obj ) {
    
    obj.children[0].geometry = BufferGeometryUtils.mergeVertices(obj.children[0].geometry);     
    obj.children[0].computeVertexNormals();

    obj.traverse( function ( node ) {

        if ( node.isMesh ) 
        {
        node.material = material;
        
        }

      } );
    scene.add(obj)
} 
);

My 2 obj files which i work with have these stats
Castle.obj
Vertices :220.153
On three.js 270.532

Ball.obj
Vertices: 95.213
on three.js 123.357

The face count remains the same. Am i doing something wrong? If i use the deprecated Geometry everything works properly however since it’s deprecated i dont know if it’s the right thing to do. Im on version 0.136

Best regards

apexcharts range bars not displayed correctly

I’m trying to display a Range Bar Chart with AppexCharts for team due date tasks (2 tasks or above).

every task can have multiple bars
if the number of bars in each task is more than 2 the bars of each task get into each other
please take a look at this example that can explain my point clearly .

Thank you .

var options = {
          series: [
             {
            name: 'task1',
            data: [
                {
                x: 'Team Health',
                y: [
                  new Date('2021-03-01').getTime(),
                  new Date('2021-03-02').getTime()
                ]
              },
                   {
                x: 'Team Health',
                y: [
                  new Date('2021-03-02').getTime(),
                  new Date('2021-03-05').getTime()
                ]
              },
                 {
                x: 'Team Health',
                y: [
                  new Date('2021-03-01').getTime(),
                  new Date('2021-03-07').getTime()
                ]
              },
                   {
                x: 'Team Health',
                y: [
                  new Date('2021-03-02').getTime(),
                  new Date('2021-03-08').getTime()
                ]
              },
                    {
                x: 'Team Health',
                y: [
                  new Date('2021-03-01').getTime(),
                  new Date('2021-03-05').getTime()
                ]
              },
        
            ]
          },
            {
            name: 'task2',
            data: [
                {
                x: 'Team Health',
                y: [
                  new Date('2021-03-01').getTime(),
                  new Date('2021-03-10').getTime()
                ]
              },
            
                 {
                x: 'Team Health',
                y: [
                  new Date('2021-03-01').getTime(),
                  new Date('2021-03-03').getTime()
                ]
              },
       
                    {
                x: 'Team Health',
                y: [
                  new Date('2021-03-3').getTime(),
                  new Date('2021-03-08').getTime()
                ]
              },
        
            ]
          },
    
        ],
          chart: {
       height:400,
          type: 'rangeBar'
        },
        plotOptions: {
          bar: {
            horizontal: true,
            barHeight: '80%',
            rangeBarOverlap: false,
      
           columnWidth: '10%',
          }
        },
        xaxis: {
          type: 'datetime',
             position: 'top',
           
        },
        stroke: {
          width: 1
        },
        fill: {
          type: 'solid',
          opacity: 0.6
        },
        legend: {
          position: 'top',
          horizontalAlign: 'center'
        }
        };

Canvas zoom to any coordinates

First of all, I did tons of research but I only found this topic related to Mouse positions.

I have a canvas element and I’m doing some zooming stuff with it (while clicking, scrolling etc.)

This function below shows how the zooming works.

    zoom(clicks) {;
        var pt = this.ctx.transformedPoint(this.X, this.Y);
        this.ctx.translate(pt.x, pt.y);
        var factor = Math.pow(this.scaleFactor, clicks);
        this.ctx.scale(factor, factor);
        
        this.totalzoom *= factor;
        this.ctx.translate(-pt.x, -pt.y);
        this.reDraw();
    }

X means mouseX

Y means mouseY

this.X = evt.offsetX;
this.Y = evt.offsetX;

These are working really fine until I want to use this functions to zoom only to a unique position. I edited my code like this to make it work somehow:

    zoomToItem(x,y){

        var pt = this.ctx.transformedPoint(x, y);
        this.ctx.translate(pt.x, pt.y);
        var factor = Math.pow(this.scaleFactor, 10);
        this.ctx.scale(factor, factor);
        
        this.totalzoom *= factor;
        this.ctx.translate(-pt.x, -pt.y);
        this.reDraw();
    }

The real problem is that in the original view the coordinates what I give is proper, but as I mentioned I scale the image to fit in the canvas, so the given coordinates won’t be proper anymore.

Here’s an example what I tried:

let transform = this.Core.Draw.ctx.getTransform();

let X = (this.item[i].x - this.rects.left - transform.e) / transform.a; 
let Y = (this.item[i].y - this.rects.top - transform.f) / transform.d;

this.zoomToItem(X,Y);

How to do server-side date conversion and styling before sending it to jQuery datatable?

I use jQuery datatable in my project. The code for getting all data from database is:

var pm = _pmRepository.GetAllPMs().Reverse().ToList();

The repository pattern used for this purpose is:

 public IEnumerable<PM> GetAllPMs()
    {
        return context.PMs;
    }

My database has some columns with DateTime format. I want to convert date format. I have written a class that can do this:

public class DateTimeConverter
{
    PersianCalendar pc = new PersianCalendar();
public string DateConverter(string inputDate)
        {
            DateTime d = DateTime.Parse(inputDate);
            string[] convertedDateString = new string[3];
            convertedDateString[0] = pc.GetYear(d).ToString();
            convertedDateString[1] = pc.GetMonth(d).ToString();
            convertedDateString[2] = pc.GetDayOfMonth(d).ToString();
            string currentConvertedDate = string.Format("{0}/{1}/{2}", 
            convertedDateString[0], convertedDateString[1],
            convertedDateString[2]);
            return currentConvertedDate;
        }
}

How can I use my date converter before sending data to datatable?