auth.go 8.1 KB

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