Skip to content

Commit 3536d03

Browse files
committed
Merge remote-tracking branch 'jeremy-clerk/jeremy-clerk/troubleshooting'
2 parents 00e3153 + 4476ccf commit 3536d03

File tree

11 files changed

+118
-70
lines changed

11 files changed

+118
-70
lines changed

.env.example

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Recommended to have an example env file for other users know what environment variables need to be set.
2+
3+
# Get your keys from the Clerk dashboard at https://dashboard.clerk.com
4+
CLERK_SECRET_KEY=sk_
5+
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_
6+
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
7+
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
8+
9+
# If using a local docker container (local-database.yml)
10+
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/lockscript?schema=public

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,6 @@ yarn-error.log*
3535
# typescript
3636
*.tsbuildinfo
3737
next-env.d.ts
38+
39+
#Intellij Editors
40+
.idea

README.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,47 @@ LockScript Vault is an open-source secure vault for passwords, cards, notes, and
1010
- Prisma
1111
- Zod
1212

13+
## Getting Started
14+
15+
Clone the repository
16+
```bash
17+
git clone [email protected]:Lockscript/Lockscript-Vault
18+
```
19+
```bash
20+
cd Lockscript-Vault
21+
```
22+
23+
Repo is using yarn as a package manager.
24+
25+
[How To Install Yarn](https://classic.yarnpkg.com/lang/en/docs/install)
26+
27+
Install dependencies
28+
```bash
29+
yarn install
30+
```
31+
32+
### Setup local database (if required)
33+
34+
Start Docker container (requires [Docker](https://docs.docker.com/engine/install/))
35+
36+
```bash
37+
docker compose -f ./local-database.yml up -d
38+
```
39+
Generate database client
40+
41+
```bash
42+
yarn run generate
43+
```
44+
```bash
45+
yarn run push
46+
```
47+
48+
### Start the dev server
49+
```bash
50+
yarn run dev
51+
```
52+
53+
1354
## How to contribute
1455

1556
We accept contributions from the community, but you must follow some rules:

local-database.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Use postgres/example user/password credentials
2+
version: '3.1'
3+
services:
4+
db:
5+
container_name: lockscript-postgres
6+
image: postgres
7+
restart: always
8+
ports:
9+
- "5432:5432"
10+
environment:
11+
POSTGRES_PASSWORD: postgres
12+
volumes:
13+
- postgres:/var/lib/postgres/data
14+
volumes:
15+
postgres:
16+
external: false
17+

package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212
"find:unused": "next-unused"
1313
},
1414
"dependencies": {
15-
"@clerk/backend": "^1.23.11",
16-
"@clerk/clerk-sdk-node": "^5.1.6",
1715
"@clerk/nextjs": "^6.11.0",
1816
"@emotion/react": "^11.14.0",
1917
"@emotion/styled": "^11.14.0",

src/app/(main)/page.tsx

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,19 @@
11
import {VaultPage} from "@/components/vault/vault-page";
2-
import prismadb from "@/lib/prismadb";
3-
import {auth} from "@clerk/nextjs/server";
4-
import {instantiateVault} from "../actions";
2+
import {auth, currentUser} from "@clerk/nextjs/server";
3+
import {getPasswords, instantiateVault} from "../actions";
54

6-
export const dynamic = "force-dynamic";
7-
8-
const Page = async () => {
5+
export default async function Page(){
96
const { userId, redirectToSignIn } = await auth();
107

118
if (!userId) return redirectToSignIn();
129

13-
const user = await prismadb.user.findUnique({
14-
where: {
15-
id: userId,
16-
},
17-
include: {
18-
passwordItems: true,
19-
cardItems: true,
20-
pinItems: true,
21-
noteItems: true,
22-
},
23-
});
10+
const user = await getPasswords(userId)
2411

2512
if (!user) {
26-
instantiateVault();
13+
const clerkUser = await currentUser()
14+
if(!clerkUser) return redirectToSignIn()
15+
await instantiateVault(clerkUser.id, clerkUser.username as string);
2716
}
2817

2918
return <VaultPage user={user} />;
3019
};
31-
32-
export default Page;

src/app/actions.ts

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -94,46 +94,29 @@ export async function createPasswordItem(
9494
throw new Error("Not authenticated");
9595
}
9696

97-
const user = await prismadb.user.findUnique({
98-
where: {
99-
id: userId,
100-
},
101-
include: {
102-
passwordItems: true,
103-
},
104-
});
105-
106-
if (!user) {
107-
throw new Error("User not found");
108-
}
109-
11097
const newPasswordItem = await prismadb.passwordItem.create({
11198
data: {
11299
username,
113100
website,
114101
password,
115102
updatedAt: new Date().toISOString(),
116103
createdAt: new Date().toISOString(),
117-
userId: user.id,
104+
user: {
105+
connect: {
106+
id: userId
107+
}
108+
}
118109
},
119110
});
120111

121112
return newPasswordItem;
122113
}
123114

124-
export async function instantiateVault() {
125-
const { userId } = await auth()
126-
127-
if (!userId) {
128-
throw new Error("Not authenticated");
129-
}
130-
131-
const user = await currentUser()
132-
115+
export async function instantiateVault(userId: string, username: string) {
133116
const vault = await prismadb.user.create({
134117
data: {
135118
id: userId,
136-
username: user?.username!,
119+
username: username,
137120
},
138121
include: {
139122
passwordItems: true,
@@ -145,3 +128,17 @@ export async function instantiateVault() {
145128

146129
return vault;
147130
}
131+
132+
export async function getPasswords(userId: string) {
133+
return prismadb.user.findUnique({
134+
where: {
135+
id: userId,
136+
},
137+
include: {
138+
passwordItems: true,
139+
cardItems: true,
140+
pinItems: true,
141+
noteItems: true,
142+
},
143+
});
144+
}

src/components/vault/dialogs/create-password-dialog.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ const initialPasswordItemState = {
2626

2727
export const CreatePasswordDialog = ({
2828
open,
29-
onClose,
29+
onClose,
3030
}: {
3131
open: boolean;
32-
onClose: () => void;
32+
onClose: ()=> void
3333
}) => {
3434
const [passwordItem, setPasswordItem] = useState(initialPasswordItemState);
3535
const [loading, setLoading] = useState(false);
@@ -156,6 +156,7 @@ export const CreatePasswordDialog = ({
156156
value={passwordItem.password}
157157
onChange={handleChange}
158158
type="password"
159+
name="password"
159160
maxLength={128}
160161
name="password"
161162
/>

src/components/vault/vault-page.tsx

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use client";
22

3-
import {deletePasswordItem} from "@/app/actions";
3+
import {deletePasswordItem, getPasswords} from "@/app/actions";
44
import {Button} from "@/components/ui/button";
55
import {Input} from "@/components/ui/input";
66
import {ScrollArea} from "@/components/ui/scroll-area";
@@ -63,13 +63,14 @@ export const VaultPage: React.FC<VaultPageProps> = ({ user }) => {
6363
const [searchQuery, setSearchQuery] = useState("");
6464
const [filteredEntries, setFilteredEntries] = useState<PasswordEntry[]>([]);
6565
const [passwords, setPasswords] = useState<PasswordEntry[]>([]);
66+
const [passwordItems, setPasswordItems] = useState(user?.passwordItems)
6667

6768
useEffect(() => {
6869
if (!clerkUser) return;
6970

70-
if (!user?.passwordItems) return;
71+
if (!user?.passwordItems || !passwordItems) return;
7172

72-
const decryptedPasswords = user.passwordItems
73+
const decryptedPasswords = passwordItems
7374
.map((item) => ({
7475
id: item.id,
7576
name: decrypt(item.username, clerkUser),
@@ -85,7 +86,7 @@ export const VaultPage: React.FC<VaultPageProps> = ({ user }) => {
8586
);
8687

8788
setPasswords(decryptedPasswords);
88-
}, [user?.passwordItems, clerkUser]);
89+
}, [user?.passwordItems, clerkUser, passwordItems]);
8990

9091
const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {
9192
setSearchQuery(e.target.value);
@@ -211,8 +212,8 @@ export const VaultPage: React.FC<VaultPageProps> = ({ user }) => {
211212
onClick={async () => {
212213
try {
213214
await deletePasswordItem(password.id);
214-
router.refresh();
215-
215+
const updatedItems = await getPasswords(user?.id as string)
216+
setPasswordItems(updatedItems?.passwordItems);
216217
if (selectedEntry?.id === password.id) {
217218
setSelectedEntry(null);
218219
}
@@ -281,10 +282,11 @@ export const VaultPage: React.FC<VaultPageProps> = ({ user }) => {
281282
)}
282283
<CreatePasswordDialog
283284
open={isCreateDialogOpen}
284-
onClose={() => {
285+
onClose={async () => {
285286
setIsCreateDialogOpen(false);
286-
router.refresh();
287287
setSelectedEntry(null);
288+
const userWithPasswords = await getPasswords(user?.id as string)
289+
setPasswordItems(userWithPasswords?.passwordItems)
288290
}}
289291
/>
290292
</div>

src/utils/encryption.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import CryptoJS from "crypto-js";
22

3+
4+
// this can be reverse engineered - please use a randomly generated string that is saved securely somewhere else.
35
const generateEncryptionPassword = (clerkUser: any) => {
46
if (!clerkUser) return "";
5-
67
return `${clerkUser.id}-${clerkUser.createdAt}-${clerkUser.createdAt?.getTime()}-${clerkUser.id.charCodeAt(clerkUser.id.length - 1)}-${clerkUser.createdAt?.getDate()}-${clerkUser.id.charCodeAt(0)}-${clerkUser.createdAt?.getUTCFullYear()}-${clerkUser.id.charCodeAt(1)}-${clerkUser.createdAt?.getUTCHours()}-${clerkUser.id.length}-${clerkUser.createdAt?.getUTCMinutes()}`;
78
};
89

10+
// See above comment - the key should be stored securely and used on subsequent encryption calls
911
export const encrypt = (data: string, clerkUser: any) => {
1012
const encryptionPassword = generateEncryptionPassword(clerkUser);
1113
return CryptoJS.AES.encrypt(data, encryptionPassword).toString();

0 commit comments

Comments
 (0)