Compare commits

...
Author SHA1 Message Date
Marcos Rodrigues Silva a5f3ef20fe Merge pull request #338 from dadosfera/bugfix/public-link
FIX: add user by bearer token if it exists
2025-07-29 09:51:17 -03:00
marcos-silva-rodrigues 467445fe05 FIX: add user by bearer token if it exists 2025-07-29 09:47:56 -03:00
Marcos Rodrigues Silva d0448f844a Merge pull request #337 from dadosfera/bugfix/google-oauth
UPDATE: more logs
2025-07-21 16:06:22 -03:00
marcos-silva-rodrigues b2299a5f2f UPDATE: more logs 2025-07-21 15:51:56 -03:00
Marcos Rodrigues Silva 9b42754c69 Merge pull request #336 from dadosfera/bugfix/google-oauth
Bugfix/google oauth
2025-07-21 15:06:49 -03:00
marcos-silva-rodrigues aee33334ac UPDATE: add log to debug 2025-07-21 15:01:41 -03:00
Marcos Rodrigues Silva b0d9f3a468 Merge pull request #334 from dadosfera/chore/stg-env
FIX: revert env
2025-07-18 10:27:01 -03:00
marcos-silva-rodrigues 5b117acaa9 FIX: revert env 2025-07-18 10:23:10 -03:00
Marcos Rodrigues Silva a5cb607650 Merge pull request #333 from dadosfera/feature/sso-openid
FIX: change env to stg
2025-07-17 16:12:51 -03:00
Marcos Rodrigues Silva debbe1c1b1 Merge pull request #332 from dadosfera/feature/sso-openid
Feature/sso openid
2025-07-16 18:50:04 -03:00
Marcos Rodrigues Silva fa46294154 Merge pull request #331 from dadosfera/feature/sso-openid
FIX: using only header origin
2025-07-16 18:37:53 -03:00
Marcos Rodrigues Silva 4e6985b572 Merge pull request #330 from dadosfera/feature/sso-openid
FIX: send redirect uri
2025-07-16 18:16:27 -03:00
Marcos Rodrigues Silva 2b3066abc9 Merge pull request #329 from dadosfera/feature/sso-openid
FIX: redis env
2025-07-16 17:57:26 -03:00
Marcos Rodrigues Silva 4a7524422d Merge pull request #328 from dadosfera/feature/sso-openid
FIX: add logger
2025-07-16 17:41:40 -03:00
Marcos Rodrigues Silva 0c75cf4619 Merge pull request #327 from dadosfera/feature/sso-openid
Feature/sso openid
2025-07-16 12:33:44 -03:00
9 changed files with 75 additions and 41 deletions
-2
View File
@@ -4,8 +4,6 @@ charts:
values:
- ../helm-chart/values.yaml
set:
- name: maestro.env
value: stg
- name: maestro.duc_url
value: duc.stg.dadosfera.ai
- name: hostname
+1 -1
View File
@@ -615,7 +615,7 @@ export const DADOSFERA_MODULES_KEYS = {
ACCESS_DASHBOARD: 'access-dashboard',
DANGER_ZONE: 'danger-zone',
PII: 'pii',
PUBLIC_ASSIGN_EMBED: 'public-assign-embed',
EMBED: 'embedded-analytics',
}
export const DADOSFERA_MODULES: Array<DadosferaModule> = [
+2 -2
View File
@@ -15,7 +15,7 @@ export class AssignController {
@RequireSomePermission(
PERMISSIONS_GROUPS.USERS.permissions.ADMIN
)
@RequireModule(DADOSFERA_MODULES_KEYS.PUBLIC_ASSIGN_EMBED)
@RequireModule(DADOSFERA_MODULES_KEYS.EMBED)
create(@Body() createAssignDto: CreateAssignDto, @User() user: RequestUser) {
const metadata = PackTheMetadata(user);
return this.assignService.create(createAssignDto, metadata);
@@ -25,7 +25,7 @@ export class AssignController {
@RequireSomePermission(
PERMISSIONS_GROUPS.USERS.permissions.ADMIN
)
@RequireModule(DADOSFERA_MODULES_KEYS.PUBLIC_ASSIGN_EMBED)
@RequireModule(DADOSFERA_MODULES_KEYS.EMBED)
async get(@User() user: RequestUser) {
const metadata = PackTheMetadata(user);
return await this.assignService.get(metadata);
+1 -1
View File
@@ -33,6 +33,6 @@ export class AssignService implements OnModuleInit {
}
async get(metadata: Metadata) {
return await lastValueFrom(this.ducService.GetAssignPublicKey(metadata))
return await lastValueFrom(this.ducService.GetAssignPublicKey({}, metadata))
}
}
@@ -26,6 +26,7 @@ export class GoogleLoginStrategy extends PassportStrategy(
callbackURL: oauthSecrets['google-login'].redirect_uri,
scope: ['email', 'profile', 'openid'],
};
console.log("GoogleLoginStrategy", options.clientID, options.callbackURL);
const verify = (
accessToken: string,
refreshToken: string,
@@ -41,23 +41,22 @@ export class ShareController {
@Get('/:id')
async getShareDataAsset(
@Param('id') id: string,
@User() user: RequestUser,
@Req() request: Request
) {
this.logger.info(`GET //:id`);
return await this.catalogShareService.getOneDataAssetPublic(id, user, request);
return await this.catalogShareService.getOneDataAssetPublic(id, request);
}
@Get('/:id/columns-metadata')
async getShareDataAssetColumnsMetadata(
@Language() language: LanguageEnum,
@Param('id') id: string,
@User() user: RequestUser
@Req() request: Request
): Promise<IColumnsMetadataResponse> {
this.logger.info(`GET /:id/columns-metadata`);
const columns_metadata =
await this.catalogShareService.getDatasetColumnsMetadata(id, user);
await this.catalogShareService.getDatasetColumnsMetadata(id, request);
return { columns_metadata };
@@ -67,10 +66,10 @@ export class ShareController {
async getShareDataAssetPreview(
@Language() language: LanguageEnum,
@Param('id') id: string,
@User() user: RequestUser
@Req() request: Request
): Promise<IPreviewResponse> {
this.logger.info(`GET /:id/preview`);
const preview = await this.catalogShareService.getDatasetPreview(id, user);
const preview = await this.catalogShareService.getDatasetPreview(id, request);
return { preview };
}
@@ -79,10 +78,10 @@ export class ShareController {
async getShareDataAssetDocs(
@Language() language: LanguageEnum,
@Param('id') id: string,
@User() user: RequestUser
@Req() request: Request
): Promise<IDocsResponse> {
this.logger.info(`GET /:id/docs`);
const docs = await this.catalogShareService.getDataDocs(id, user);
const docs = await this.catalogShareService.getDataDocs(id, request);
return { docs };
}
+3 -1
View File
@@ -9,6 +9,7 @@ import { ShareController } from "./share.controller";
import DadosferaLogger from "@dadosfera/dadosfera-logs";
import { ShareService } from "./share.service";
import { MixpanelModule } from "src/modules/mixpanel/mixpanel.module";
import { AuthModule } from "src/modules/auth/auth.module";
const client = new CatalogClientConfiguration();
@@ -19,7 +20,8 @@ const client = new CatalogClientConfiguration();
RolesModule,
CustomersModule,
ShareMetadataModule,
MixpanelModule
MixpanelModule,
AuthModule
],
controllers: [ShareController],
providers: [ShareService, DadosferaLogger],
+53 -25
View File
@@ -22,6 +22,9 @@ import { ShareMetadataService } from 'src/modules/share-metadata/share-metadata.
import { isJWT } from 'class-validator';
import { MixpanelService } from 'src/modules/mixpanel/mixpanel.service';
import { Request } from 'express';
import jwt from 'jsonwebtoken';
import { AuthClientService } from 'src/modules/auth/auth.service';
export class ShareService implements OnModuleInit {
catalogReadService: ReadService.CatalogReadServices;
@@ -36,6 +39,7 @@ export class ShareService implements OnModuleInit {
private readonly roleService: RolesService,
private readonly shareMetadataService: ShareMetadataService,
private readonly mixpanelService: MixpanelService,
private authClient: AuthClientService,
) {
this.logger = dadosferaLogger.logger;
}
@@ -47,8 +51,8 @@ export class ShareService implements OnModuleInit {
);
}
async getDatasetColumnsMetadata(id: string, user: RequestUser) {
const shareMetadata = await this.getShareMetadata(id, user);
async getDatasetColumnsMetadata(id: string, request: Request) {
const shareMetadata = await this.getShareMetadata(id, request);
const metadata = PackTheMetadata({
customer_id: shareMetadata.customerId,
customer_name: shareMetadata.customerName,
@@ -63,8 +67,8 @@ export class ShareService implements OnModuleInit {
return result;
}
async getDatasetPreview(id: string, user: RequestUser) {
const shareMetadata = await this.getShareMetadata(id, user);
async getDatasetPreview(id: string, request: Request) {
const shareMetadata = await this.getShareMetadata(id, request);
const metadata = PackTheMetadata({
customer_id: shareMetadata.customerId,
customer_name: shareMetadata.customerName,
@@ -79,14 +83,14 @@ export class ShareService implements OnModuleInit {
return result;
}
async getOneDataAssetPublic(id: string, user: RequestUser, request: Request) {
async getOneDataAssetPublic(id: string, request: Request) {
this.logger.info("getOneDataAssetPublic: " + JSON.stringify({
id,
userId: user?.user_id,
customerId: user?.customer_id
id
}))
try {
const shareMetadata = await this.getShareMetadata(id, user);
const user = await this.getUserFromRequest(request);
const shareMetadata = await this.getShareMetadata(id, request);
const mixpanelTracker = {
asset: shareMetadata.assetId,
@@ -148,8 +152,8 @@ export class ShareService implements OnModuleInit {
return { data_asset: asset[0] };
}
async getDataDocs(id: string, user: RequestUser) {
const shareMetadata = await this.getShareMetadata(id, user);
async getDataDocs(id: string, request: Request) {
const shareMetadata = await this.getShareMetadata(id, request);
const metadata = PackTheMetadata({
customer_id: shareMetadata.customerId,
customer_name: shareMetadata.customerName,
@@ -197,21 +201,8 @@ export class ShareService implements OnModuleInit {
});
}
// private async validateShareAssign(token: string) {
// const tokenDecoded = jwt.decode(token, {
// complete: true,
// });
// jwt.verify(token, this.pemValue, {
// algorithms: ['RS256'],
// });
// const shareId = (tokenDecoded.payload as JwtPayload).sub;
// const metadata = PackTheMetadata({});
// return await this.shareMetadataService.get(shareId, metadata);
// }
private async getShareMetadata(id: string, user: RequestUser) {
private async getShareMetadata(id: string, request: Request) {
const metadata = PackTheMetadata({});
this.logger.info('GET share metadata')
const info = await this.shareMetadataService.get(id, metadata);
@@ -219,6 +210,8 @@ export class ShareService implements OnModuleInit {
return info;
}
const user = await this.getUserFromRequest(request);
if (info.type === 'private') {
if (!user) {
throw new ForbiddenException(
@@ -244,4 +237,39 @@ export class ShareService implements OnModuleInit {
}
return info;
}
private async getUserFromRequest(request: Request): Promise<RequestUser | null> {
const accessToken = request.get('Authorization');
if (accessToken) {
const accessTokenDecoded: any = jwt.decode(accessToken, {
complete: true,
});
const { kid } = accessTokenDecoded.header;
const { keys } = await this.authClient.getPublicKeys();
const pemValue = keys.find((key) => key.kid === kid);
if (!pemValue) {
return null;
}
jwt.verify(accessToken, pemValue.pem);
const accessTokenPayload = accessTokenDecoded.payload;
return {
user_id: accessTokenPayload.user_id,
username: accessTokenPayload.username,
permissions: accessTokenPayload.permissions,
customer_id: accessTokenPayload.customer_id,
customer_name: accessTokenPayload.customer_name,
customer_tier: accessTokenPayload.customer_tier,
customer_modules: accessTokenPayload.customer_modules,
access_token: accessToken,
};
}
return null;
}
}
+7 -1
View File
@@ -24,15 +24,21 @@ export async function getOauthSecrets() {
const path = process.env.SM_OAUTH_PATH;
const secretsManagerClient = new SecretsManagerClient({});
for (const key in secrets) {
console.log(`Fetching secret for ${key} from path ${path}/${key}`);
const getSecretComand = new GetSecretValueCommand({
SecretId: `${path}/${key}`,
});
const res = await secretsManagerClient
.send(getSecretComand)
.catch(() => null);
.catch((err) => {
console.error(`Error fetching secret for ${key}:`, err);
return null;
});
if (res) {
secrets[key] = JSON.parse(res.SecretString);
console.log(JSON.parse(res.SecretString).client_id)
} else {
console.log("No secret found for", key);
secrets[key] = {
client_id: 'id',
client_secret: 'id',