diff --git a/NodeApp/src/managers/GitlabManager.ts b/NodeApp/src/managers/GitlabManager.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6290490cea66b430ee699ca6dce33bbb4085267c
--- /dev/null
+++ b/NodeApp/src/managers/GitlabManager.ts
@@ -0,0 +1,108 @@
+import LocalConfig     from '../Config/LocalConfig/LocalConfig';
+import LocalConfigKeys from '../Config/LocalConfig/LocalConfigKeys';
+import axios           from 'axios';
+import Config          from '../Config/Config';
+import ora             from 'ora';
+
+
+class GitlabManager {
+    private _token: string | null = null;
+
+    constructor() { }
+
+    private static _instance: GitlabManager;
+
+    public static get instance(): GitlabManager {
+        if ( !GitlabManager._instance ) {
+            GitlabManager._instance = new GitlabManager();
+        }
+
+        return GitlabManager._instance;
+    }
+
+    get isLogged(): boolean {
+        return this._token !== null;
+    }
+
+    get token(): string {
+        return this._token || '';
+    }
+
+    set token(token: string) {
+        this._token = token;
+
+        LocalConfig.updateConfig(LocalConfigKeys.GITLAB_PERSONAL_TOKEN, token);
+    }
+
+    public async testToken(verbose: boolean = true): Promise<[ boolean, boolean ]> {
+        let result: [ boolean, boolean ] = [ false, false ];
+
+        type NotificationSettings = { level: string }
+
+        let notificationSettings: NotificationSettings = { level: 'error' };
+
+        // Test read access
+        {
+            const spinnerRead: ora.Ora = ora('Read access');
+            if ( verbose ) {
+                spinnerRead.start();
+            }
+
+
+            try {
+                notificationSettings = (await this.getNotificationSettings()).data as NotificationSettings;
+
+                result[0] = true;
+
+                if ( verbose ) {
+                    spinnerRead.succeed();
+                }
+            } catch ( e ) {
+                if ( verbose ) {
+                    spinnerRead.fail();
+                }
+            }
+        }
+
+        // Test write access
+        {
+            const spinnerWrite: ora.Ora = ora('Write access');
+            if ( verbose ) {
+                spinnerWrite.start();
+            }
+
+            const someLevelTypes = [ 'disabled', 'participating' ];
+
+            try {
+                const oldSettings = notificationSettings;
+                const newSettings = { level: someLevelTypes[someLevelTypes[0] == oldSettings.level ? 1 : 0] };
+
+                await this.setNotificationSettings(newSettings);
+                await this.setNotificationSettings(oldSettings);
+
+                result[1] = true;
+
+                if ( verbose ) {
+                    spinnerWrite.succeed();
+                }
+            } catch ( e ) {
+                if ( verbose ) {
+                    spinnerWrite.fail();
+                }
+            }
+        }
+
+        return result;
+    }
+
+    public getNotificationSettings() {
+        return axios.get(`${ Config.gitlabApiURL }/notification_settings`);
+    }
+
+    public setNotificationSettings(newSettings: any) {
+        return axios.put(`${ Config.gitlabApiURL }/notification_settings`, { params: new URLSearchParams(newSettings) });
+    }
+}
+
+
+export default GitlabManager.instance;