Skip to content

Commit

Permalink
feat: allow unauthenticated uploads
Browse files Browse the repository at this point in the history
  • Loading branch information
stonith404 committed Oct 18, 2022
1 parent 41c3baf commit 84d29df
Show file tree
Hide file tree
Showing 17 changed files with 340 additions and 249 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ APP_URL=http://localhost:3000
SHOW_HOME_PAGE=true
ALLOW_REGISTRATION=true
MAX_FILE_SIZE=1000000000
ALLOW_UNAUTHENTICATED_SHARES=false

# SECURITY
JWT_SECRET=long-random-string
1 change: 1 addition & 0 deletions backend/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
APP_URL=http://localhost:3000
ALLOW_REGISTRATION=true
MAX_FILE_SIZE=5000000000
ALLOW_UNAUTHENTICATED_SHARES=false

# SECURITY
JWT_SECRET=random-string
4 changes: 2 additions & 2 deletions backend/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ model Share {
views Int @default(0)
expiration DateTime
creatorId String
creator User @relation(fields: [creatorId], references: [id])
creatorId String?
creator User? @relation(fields: [creatorId], references: [id])
security ShareSecurity?
files File[]
}
Expand Down
7 changes: 7 additions & 0 deletions backend/src/auth/guard/jwt.guard.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import { ExecutionContext } from "@nestjs/common";
import { AuthGuard } from "@nestjs/passport";
import { Observable } from "rxjs";

export class JwtGuard extends AuthGuard("jwt") {
constructor() {
super();
}
canActivate(
context: ExecutionContext
): boolean | Promise<boolean> | Observable<boolean> {
return process.env.ALLOW_UNAUTHENTICATED_SHARES == "true" ? true : super.canActivate(context);
}
}
1 change: 1 addition & 0 deletions backend/src/auth/strategy/jwt.strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export class JwtStrategy extends PassportStrategy(Strategy) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: config.get("JWT_SECRET"),

});
}

Expand Down
2 changes: 2 additions & 0 deletions backend/src/share/guard/shareOwner.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export class ShareOwnerGuard implements CanActivate {

if (!share) throw new NotFoundException("Share not found");

if(!share.creatorId) return true;

return share.creatorId == (request.user as User).id;
}
}
6 changes: 4 additions & 2 deletions backend/src/share/share.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export class ShareService {
private jwtService: JwtService
) {}

async create(share: CreateShareDTO, user: User) {
async create(share: CreateShareDTO, user?: User) {
if (!(await this.isShareIdAvailable(share.id)).isAvailable)
throw new BadRequestException("Share id already in use");

Expand Down Expand Up @@ -58,7 +58,7 @@ export class ShareService {
data: {
...share,
expiration: expirationDate,
creator: { connect: { id: user.id } },
creator: { connect: user ? { id: user.id } : undefined },
security: { create: share.security },
},
});
Expand Down Expand Up @@ -154,6 +154,8 @@ export class ShareService {
});

if (!share) throw new NotFoundException("Share not found");
if (!share.creatorId)
throw new ForbiddenException("Anonymous shares can't be deleted");

await this.fileService.deleteAllFiles(shareId);
await this.prisma.share.delete({ where: { id: shareId } });
Expand Down
1 change: 1 addition & 0 deletions frontend/.env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
SHOW_HOME_PAGE=true
ALLOW_REGISTRATION=true
MAX_FILE_SIZE=1000000000
ALLOW_UNAUTHENTICATED_SHARES=false
1 change: 1 addition & 0 deletions frontend/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const nextConfig = {
ALLOW_REGISTRATION: process.env.ALLOW_REGISTRATION,
SHOW_HOME_PAGE: process.env.SHOW_HOME_PAGE,
MAX_FILE_SIZE: process.env.MAX_FILE_SIZE,
ALLOW_UNAUTHENTICATED_SHARES: process.env.ALLOW_UNAUTHENTICATED_SHARES
}
}

Expand Down
219 changes: 0 additions & 219 deletions frontend/src/components/share/CreateUploadModalBody.tsx

This file was deleted.

19 changes: 19 additions & 0 deletions frontend/src/components/upload/ExpirationPreview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import moment from "moment";

const ExpirationPreview = ({ form }: { form: any }) => {
const value = form.values.never_expires
? "never"
: form.values.expiration_num + form.values.expiration_unit;
if (value === "never") return "This share will never expire.";

const expirationDate = moment()
.add(
value.split("-")[0],
value.split("-")[1] as moment.unitOfTime.DurationConstructor
)
.toDate();

return `This share will expire on ${moment(expirationDate).format("LLL")}`;
};

export default ExpirationPreview;
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import moment from "moment";
import getConfig from "next/config";
import { useRouter } from "next/router";
import { TbCopy } from "react-icons/tb";
import { Share } from "../../types/share.type";
import toast from "../../utils/toast.util";
import { Share } from "../../../types/share.type";
import toast from "../../../utils/toast.util";

const { publicRuntimeConfig } = getConfig();

Expand Down
Loading

0 comments on commit 84d29df

Please sign in to comment.