auth.go 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. package tst
  2. import (
  3. . "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/common"
  4. TS "git.eugeniocarvalho.dev/eugeniucarvalho/gg/generators/typescript"
  5. )
  6. func createAuthClass(p *Project, file *TS.File) {
  7. // auth := p.Auth.Oauth2
  8. // scope, _ := json.Marshal(auth.Client.Scope)
  9. file.Line().Comment(
  10. "Class gerencia autenticacao e autorizacao da api.",
  11. ).Export().Class().Id("Auth").Block(TS.Raw(`
  12. // public profile = new Subject<any>();
  13. public profile$ = new Subject<any>();
  14. public profile: any;
  15. public cookieDomain: string;
  16. public grant: any;
  17. public onAuthorize$ = new BehaviorSubject(null);
  18. public clientParams = {
  19. redirect_uri: '',
  20. client_id: '',
  21. client_secret: '',
  22. scope: [],
  23. state: '',
  24. };
  25. protected oauthURI: string;
  26. // constructor(protected api: `).Id(ApiClassName(p)).Raw(`) {
  27. constructor(protected api: ApiInterface) {
  28. const options = api.apiOptions;
  29. this.oauthURI = options.ACCOUNT_URL;
  30. this.clientParams = {
  31. redirect_uri: options.REDIRECT_URI,
  32. client_id: options.CLIENT_ID,
  33. client_secret: options.CLIENT_SECRET,
  34. scope: options.SCOPES,
  35. state: this.state()
  36. };
  37. this.cookieDomain = options.COOKIE_DOMAIN;
  38. console.log("create auth instance", options);
  39. }
  40. protected state() {
  41. // return [32, 7, 28].map(k => { return Math.random().toString(k).substr(2) }).join('+');
  42. return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
  43. const r = Math.random() * 16 | 0;
  44. const v = c === 'x' ? r : (r & 0x3 | 0x8);
  45. return v.toString(16);
  46. });
  47. }
  48. getProfile() {
  49. if (this.profile) {
  50. return of(this.profile).pipe(take(1));
  51. }
  52. return this.api.http
  53. .post<any>(`).Raw("`${this.oauthURI}/api/profile`").Raw(`, {}, this.api.options())
  54. .pipe(
  55. take(1),
  56. map(profile => this.profile = profile),
  57. );
  58. }
  59. Authorize(): Observable<any> {
  60. return this.getAuthCode().pipe(
  61. take(1),
  62. switchMap(code => {
  63. // console.log('(get code)', code);
  64. return this.getAccessToken({ code });
  65. }),
  66. catchError(err => {
  67. console.log('(catch erro grant)', err);
  68. switch (err) {
  69. case '':
  70. return this.getAccessToken({
  71. request_type: 'refreshToken',
  72. refresh_token: this.grant.refresh_token
  73. });
  74. case '':
  75. err = { type: err };
  76. }
  77. throw err;
  78. }),
  79. tap(grant => {
  80. // console.log('(set grant )', grant);
  81. this.setGrant(grant);
  82. // this.api.poolReady.map(callback => callback());
  83. this.onAuthorize$.next(grant);
  84. }),
  85. );
  86. }
  87. Token() {
  88. const g = this.grant;
  89. if (g) {
  90. return `).Raw("`${g.token_type} ${g.access_token}`;").Raw(`
  91. }
  92. return '';
  93. }
  94. Unauthorize() {
  95. // ${this.oauthURI}/api/signout
  96. window.location.href = `).Raw("this.location('/api/signout').href").Raw(`;
  97. }
  98. protected getAccessToken(options: any) {
  99. if (this.grant) {
  100. return of(this.grant);
  101. }
  102. const params = Object.assign({
  103. request_type: 'accessToken',
  104. client_id: this.clientParams.client_id,
  105. state: this.clientParams.state
  106. }, options);
  107. return this.api.http.post<any>(`).Raw("`${this.oauthURI}/oauth2/token`").Raw(`, {},
  108. Object.assign({}, this.api.httpOptions, { params: params })
  109. );
  110. }
  111. protected setGrant(grant) {
  112. this.grant = grant;
  113. // recupera os dados do usuario
  114. setTimeout(() => this.getProfile().subscribe(data => this.profile$.next(data)));
  115. }
  116. protected location(path = '/oauth2/authorize'): URL {
  117. // Solicita autorização par ao servidor de autenticacao caso não exista um token e nem um codigo
  118. const url = new URL(`).Raw("`${this.oauthURI}${path}`").Raw(`);
  119. Object.keys(this.clientParams).map((k, v) => {
  120. url.searchParams.append(k, this.clientParams[k]);
  121. });
  122. return url;
  123. }
  124. protected getAuthCode() {
  125. return new Observable<string>(ob => {
  126. const oauth2 = document.createElement('iframe'),
  127. url = this.location();
  128. oauth2.id = `).Raw("`iframe-${Math.random().toString(36)}`").Raw(`;
  129. url.searchParams.set('redirect_uri', oauth2.id);
  130. function listenAccessCode(event) {
  131. // Check sender origin to be trusted
  132. // if (event.origin !== "http://example.com") return;
  133. const { type, code } = event.data;
  134. if (type === 'access_code') {
  135. // remove o iframe do dom
  136. oauth2.remove();
  137. // submete o codigo
  138. if (code) { ob.next(code); } else { ob.error(event.data); }
  139. window.removeEventListener('message', listenAccessCode, false);
  140. }
  141. }
  142. window.addEventListener('message', listenAccessCode, false);
  143. oauth2.src = url.href;
  144. document.body.appendChild(oauth2);
  145. oauth2.onload = () => {
  146. if (!oauth2.contentDocument) {
  147. window.postMessage({ 'type': 'access_code', 'error': 'unauthorized' }, '*');
  148. }
  149. }
  150. });
  151. }
  152. `))
  153. }
  154. // return new Observable<any>(observer => {
  155. // // Verifica se existe um usuario logado
  156. // // Quando o usuario não está logado ele é redirecionado para o servidor de autenticacao
  157. // if (!(`).Raw(fmt.Sprintf("/\\s%s=([^;]+);?/gm.exec(", p.Auth.AuthTokenID)).Raw("` ${document.cookie}`").Raw(`))) {
  158. // window.location.href = this.location('/signin').href;
  159. // }
  160. // const res = (g, success = true) => {
  161. // let f;
  162. // if (success) {
  163. // observer.next(g);
  164. // while (f = this.api.poolReady.shift()){
  165. // f();
  166. // }
  167. // } else {
  168. // observer.error(g);
  169. // }
  170. // observer.complete();
  171. // };
  172. // // Se existe um token de authorizacao
  173. // if (this.grant) {
  174. // this.setGrant(this.grant);
  175. // res(this.grant);
  176. // return;
  177. // }
  178. // this.getAuthCode().subscribe(
  179. // code => {
  180. // const done = (grant) => {
  181. // this.setGrant(grant);
  182. // res(this.grant);
  183. // };
  184. // this.getAccessToken({
  185. // code: code
  186. // }).subscribe(
  187. // grant => done(grant),
  188. // _ => {
  189. // // Falha ao recuperar o token ( não existe ou expirou)
  190. // this.getAccessToken({
  191. // request_type: 'refreshToken',
  192. // refresh_token: this.grant.refresh_token
  193. // }).subscribe(
  194. // grant => done(grant),
  195. // error => res(error, false)
  196. // );
  197. // });
  198. // },
  199. // // Não conseguiu obter o codigo de autenticacao
  200. // // acao tomada: redirecionar para a tela de login do sistema
  201. // error => {
  202. // // window.location.href = `).Raw("`${this.oauthURI}/signout`").Raw(`;
  203. // }
  204. // );
  205. // });